[Solved]-Migrating models of dependencies when changing DEFAULT_AUTO_FIELD


Ideally, your third party dependencies would include this line in the config found in apps.py:

from django.apps import AppConfig

class ExampleConfig(AppConfig):
    default_auto_field = 'django.db.models.AutoField'

While waiting for upstream dependencies to update their apps.py or migration files, you can override the app config yourself. If it doesn’t exist already, create an apps.py file in your main app directory (eg: project/apps.py), and override the config of a dependency. In this example, I’m overriding the config of django-allauth:

from allauth.account.apps import AccountConfig
from allauth.socialaccount.apps import SocialAccountConfig

class ModifiedAccountConfig(AccountConfig):
    default_auto_field = 'django.db.models.AutoField'

class ModifiedSocialAccountConfig(SocialAccountConfig):
    default_auto_field = 'django.db.models.AutoField'

Then modify INSTALLED_APPS in settings.py to look like this, replacing the old entries for django-allauth in this example:

    # ....
    # replace: "allauth.account", with
    # replace: "allauth.socialaccount", with

If the dependency doesn’t have an apps.py file to override, you can still create an AppConfig sub-class in project/apps.py like this:

from django.apps import AppConfig

class ModifiedExampleDependencyConfig(AppConfig):
    name = 'exampledependency' # the python module
    default_auto_field = 'django.db.models.AutoField'

Now when you run python manage.py makemigrations, no migration files should be created for the dependencies.



I work on a big project, we upgraded Django from 2.2. to 3.2 and then have got a need to create all new models with Big Integer (Int8) (PostgreSQL) field instead of default Integer (Int4).

When I defined it in settings.py:

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

I got the same problem, but with own apps – Django tried to make me to migrate 135 models I had, but I didn’t want to do it. I only wanted to create new models with BigInt and manipuate olds manually.

I found the next solution. I changed the field to custom:

DEFAULT_AUTO_FIELD = 'project.db.models.CustomBigAutoField'

And then overrided its deconstruction:

from django.db import models

class CustomBigAutoField(models.BigAutoField):
    """Int8 field that is applied only for new models."""

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        if getattr(self, 'model', None):
            path = 'django.db.models.AutoField'
        return name, path, args, kwargs

As I discovered, fields of new models don’t have a back reference to their models, so path wouldn’t be overridden for them.
We override path because Django checks whether a model is changed by a key, that includes the path to this field. So we deceive Django and it thinks that existing model didn’t changed.

I might not see the whole picture, but I tested it with different existing and new models and it worked for me. If someone tells me why this solution is bad, I’d be grateful.

Leave a comment