Django lets you replace the default User model with your own through AUTH_USER_MODEL — but only before the first migration. The safest approach: create a custom User as soon as you start the project, even if you do not need extra fields yet, because later on, just wanting to add a single field like a phone number will cost you a manual migration.

The Problem

When you start out, using Django’s auth.User directly is the easiest option: login, admin, and permissions all work out of the box. The trouble only appears a few months later, when the boss asks you to store a phone number, birth date, or avatar for each account. By then AUTH_USER_MODEL is already “stuck” to a pile of old migrations, and Django will not let you change the user model after the database has migrated. To change it, you have to edit migrations by hand, or delete the database and start over — both are painful, especially once the project holds real data.

# models.py — cách làm "tiện tay" lúc đầu, và là cái bẫy về sau
from django.contrib.auth.models import User
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)

The code above works fine today, but it locks the project into auth.User. Every ForeignKey pointing straight at the default model will have to be rewritten if you ever change your mind.

The Solution

Create an accounts app as soon as you start the project, before the first migrate, then declare your own user model:

# settings.py
AUTH_USER_MODEL = "accounts.User"
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
phone = models.CharField(max_length=15, blank=True)
birth_date = models.DateField(null=True, blank=True)

Subclassing AbstractUser keeps all the default fields and behavior — username, hashed password, groups, permissions — you only add new fields. To show the model in the admin, register it with the built-in UserAdmin:

# accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)

Everywhere else in the project, point at the user with settings.AUTH_USER_MODEL in ForeignKey definitions, and get_user_model() in running code:

# blog/models.py — trỏ tới user bằng AUTH_USER_MODEL, không import trực tiếp
from django.conf import settings
from django.db import models
class Post(models.Model):
author = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE
)
title = models.CharField(max_length=200)

Run makemigrations and then migrate as usual. From now on, adding a new field to accounts means adding one line to the model and migrating — no more hand-editing migrations or deleting the database.

Apply It to Your Project

Make this a default step in your project setup checklist: create the accounts app, declare AUTH_USER_MODEL, and run the first migration before writing any other model. Even if you need no extra fields today, the cost of an “empty” custom model is almost zero, while the cost of fixing it later can be an entire afternoon untangling migrations. Remember the rule: the user model is the foundation — pour the foundation before you build the house, not after the house is finished.

Related Posts

Frequently Asked Questions

I already migrated — what happens if I want to change the User model now?

It is very hard. Django does not support changing AUTH_USER_MODEL once migrations reference the old user — you have to edit the migrations by hand, or create a new database and migrate the data over. If the project is still in development and holds no important data, deleting the database and starting over is the cleanest option.

Should I subclass AbstractUser or AbstractBaseUser?

Use AbstractUser in 99% of cases: you keep the username, password, groups, and permissions, and only add fields. Use AbstractBaseUser only when you want to replace the login method entirely — for example, logging in with email instead of username — because then you must write your own manager, required fields, and admin form.

Should I use get_user_model() or settings.AUTH_USER_MODEL?

Use settings.AUTH_USER_MODEL in ForeignKey and ManyToManyField definitions to avoid circular imports while Django loads models. Use get_user_model() in running code — views, forms, signals — when you need the actual User class. The two are not interchangeable.

Do I need a custom UserManager?

No, if you subclass AbstractUser and keep the username as the login field. You only need a custom manager when you change USERNAME_FIELD — for example, logging in with email — in which case you must define how users and superusers are created.

References