Django provides a built-in User model for authentication. When application requirements go beyond the default fields, Django allows creating a custom user model using AbstractUser or AbstractBaseUser.
AbstractUserAbstractBaseUserAbstractUser keeps all default fields and behavior while allowing additional fields.
AbstractBaseUser provides only authentication essentials and requires full implementation of user logic.
# Extending Django's built-in User model
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
birth_date = models.DateField(null=True, blank=True)
profile_picture = models.ImageField(upload_to='profile_pics/', null=True, blank=True)
# settings.py → AUTH_USER_MODEL = 'myapp.CustomUser'
# Creating a fully custom user model
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class CustomUserManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Email is required")
user = self.model(email=email, username=username)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password=None):
user = self.create_user(email, username, password)
user.is_admin = True
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=100, unique=True)
birth_date = models.DateField(null=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.username
# settings.py → AUTH_USER_MODEL = 'myapp.CustomUser'
The first approach is ideal for minor customization. The second is used when authentication logic itself must change, such as email-based login.
Configure options below to see how the code structure changes dynamically.
# Generated code will appear here...
AbstractUser unless full control is requiredAbstractUserAbstractBaseUser