When you start a Django project a custom user model is super important, otherwise you will be stuck with the default model. The default model has multiple issues with it. The major one being that the username must be unique. In most applications the username is only shown to the user themselves, so its pointless. Further you may want other fields attached to the user that doesn’t already exist. This is a tutorial for myself and for you to quickly get started on building custom user models in Django.
Step 1: Setting up the Django Project:
In the code below, we start the project and start an app called users. Users will hold all the models and code required for the custom user model. You will also need to setup your database etc. I have left that out of this tutorial as iits not related to the topic at hand.
django-admin start-project my_app
django-admin start-app users
Step 2: Setting up Settings
In this step we will set up the settings.py file to use the user app that we generated. At this stage you will see errors, so you could move this to the bottom if you prefer. Add in the following to settings.py
INSTALLED_APPS = [
...
'users', #This is new
...
]
AUTH_USER_MODEL = 'users.CustomUser'
Step 3: Django Custom User Model App
In this step we will go through setting up the custom user model app. When doing this step you have two options, one to provide all the fields yourself or to use django provided fields. I chose the latter approach mainly because I only wanted to remove the unique constraint.
Your models file should look like the one below, add in any fields you feel is necessary for you:
from django.db import models
# Create your models here.
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from .managers import CustomUserManager
class CustomUser(AbstractUser):
username = models.TextField(_('Username'), blank=True)
email = models.EmailField(_('email address'), unique=True)
first_name = models.TextField(_('first name'), blank=True)
last_name = models.TextField(_('last name'), blank=True)
joined = models.DateTimeField(_('date joined'),default=timezone.now, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
When you try to save this there will be an error. This is because Custom User manager does not exist. To resolve this we need to create a file called managers.py. It should contain the following:
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password=None, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
if password:
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
All this does is set the email as the unique field and overwrite the base class. The next step is to create forms, so we can edit the fields as necessary. Edit the fields list to be able to edit the fields that you set earlier.
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('email','first_name','last_name','joined',)
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('email','first_name','last_name','joined',)
The final thing you need to do is register it to admin.py. In the admin.py page what you need to do is seen below:
from django.contrib import admin
# Register your models here.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ('email','first_name','last_name', 'is_staff', 'is_active',)
list_filter = ('first_name','last_name','email', 'is_staff', 'is_active',)
fieldsets = (
(None, {'fields': ('email', 'first_name', 'last_name','password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(CustomUser, CustomUserAdmin)
What we have done is register the custom user model, and set up display and filter variables.
Step 4: Django Custom User Model
The final step is to make migrations and migrate. This can be running the following commands.
manage.py makemigrations
manage.py migrate
Conclusion
We have set up a custom user model in Django with the email as the unique field. You should be able to add additional fields in models.py. If you have enjoyed this article.
Django Resources: