By using our website, you agree to our privacy policy

Django: Changing User Model in Mid-Project

Django: Changing User Model in Mid-Project

Every now and then I see some questions pop up in StackOverflow with title:

ValueError: Related model ‘app.User’ cannot be resolved

This is a very common issue and pops up when the user tries to run the migration. So, lets talk more about what is this problem and how can we solve it.

The problem

This error occurs when you have been using Django’s default User model, and in mid project, you need some changes in auth.User model and decided to use CustomUser.

Why It occurs

As per documentation:

Changing AUTH_USER_MODEL after you’ve created database tables is significantly more difficult since it affects foreign keys and many-to-many relationship.

As auth.User is core part of Django, and when you change the tables, it can’t work properly. This problem is hard to identify even for myself, because of the error it throws due to migration.

How to resolve it

Easy way

The easiest(and cleanest) way is to delete all your migration files from all apps, drop the database. Then create a new database and connect your project to that. Then run python makemigrations and python migrate to make changes in DB. Means to make a clean start for the project, data wise.

Hard Way

Dropping the Database is not always possible for us. So there is an another approach to resolve this issue(based on ticket #25313):

  1. Create a custom user model identical to auth.User, call it User (so many-to-many tables keep the same name) and set db_table='auth_user' (so it uses the same table). Like this:

    from django.contrib.auth.models import AbstractUser
    class User(AbstractUser):
        class Meta:
  2. Throw away all your migrations from all the apps(except for file inside the migrations folder).

  3. Now update value of AUTH_USER_MODEL in your with myapp.User(Custom User Model) like AUTH_USER_MODEL = 'myapp.User'.

  4. Recreate a fresh set of migrations using python makemigrations.

  5. Make a backup of your database.

  6. Delete all entries from django_migrations table.

  7. Fake-apply the new set of migrations using python migrate --fake.

  8. Optional: Set db_table="your_custom_table" or remove it altogether.

  9. Make other changes to the custom model, generate migrations, apply them.

Alternative way

You can take a different approach rather than overriding you auth.User model. You can define a new model(lets say Profile), and put your relevant fields there. Then, make a OneToOne relation with auth.User like this:

class Profile(models.Model):
    user = models.OneToOneField(User)
    some_field = models.CharField(max_length=255, null=True, blank=True, default=None)

You can use post_save signals to create a profile automatically every time a User is created.

from django.dispatch import receiver
from django.core.signals import post_save
from django.contrib.auth.models import User

@receiver(post_save, sender=User)
def create_user_profile(sender, instance=None, created=None, **kwargs):
    if created:

You can use this easily in python:

user = User.objects.first()
user.profile.some_field  # Thus you get value of some field from Profile
# OR
profile = Profile.objects.first()
user = profile.user  # Thus you get auth.User

Or in template:

{{ user.profile.some_field }}

FYI: this process was mentioned in the documentation as well.

For future projects

For future projects, you should use your CustomUser model from the beginning. It will reduce a lot of hassle when it comes to customizing User.

In conclusion

To Be Honest, this an old problem and there is no good way to resolve it(at least not in Django 2.1). Hopefully in future releases, it will be fixed.

Last updated: May 27, 2020

  • x0


Share Your Thoughts
M ↓   Markdown

Monday, January 21, 2019

Thanks i was been struggling with this for some months, maybe you should be more specific with the number 1 of the HardWay of how to create an identical auth.User i just get the code from AbstractUser i just test on my development enviroment and works fine.

Arnab Kumar Shil
Tuesday, January 22, 2019

Okay, I will update the post accordingly.

Monday, August 12, 2019
Monday, August 12, 2019

I’m unsure how to design the ‘views’ for this solution. My current view saves the form inputs to the default User model and cannot get it to save to the new model. I also hit this ‘uniqueconstraint’ problem.

Wednesday, February 5, 2020

Thank you for this post. My query was that if we drop all the default tables created by Django’s makemigration command, will it affect the execution of the API catastrophically or can be managed with those tables. The reason is, those tables are considered to be Junk data. Kindly guide.

Thursday, February 6, 2020

It shouldn’t affect if you are following this procedure. But before doing anything, please make a backup of your database.