slezica slezica - 1 month ago 20
Python Question

Django: ContentTypes during migration while running tests

I migrated a

ForeignKey
to a
GenericForeignKey
, using the
contrib.contenttypes
framework. To access the
ContentType
object I need to migrate the data, I used this code:

ContentType = apps.get_model('contenttypes', 'ContentType')

my_model_content_type = ContentType.objects.get(
app_label='my_app',
model='my_model'
)


The migration works when I run
manage.py migrate
, and I can then play with the updated model in the shell without problems.

However, when I attempt to run
manage.py test
, I get the following error in the
ContentTypes.object.get()
line:

__fake__.DoesNotExist: ContentType matching query does not exist.


Querying for
ContentType.objects.all()
at that time returns an empty queryset.

I have tried (as directed by another answer here in SO) to run this before my query, but to no avail:

update_contenttypes(apps.app_configs['contenttypes'])
update_contenttypes(apps.app_configs['my_app'])


How can I ensure that the
ContentType
rows exist at that point in the test database migration?

Answer

This is what ended up working for me. First, import update_contenttypes:

from django.contrib.contenttypes.management import update_contenttypes

Second, list the initial ContentType migration as a dependency:

dependencies = [
    ('contenttypes', '0001_initial'),
    ...
]

Finally, in the forward migration function (invoked via RunPython in the migration operations):

# Ensure ContentType objects exist at this point:
app_config = apps.get_app_config('my_app')
app_config.models_module = app_config.models_module or True

update_contenttypes(app_config)

You may need to run the above code for more than one app_config. You can obtain the all the app_config objects using apps.get_app_configs() and iterate.