Creating a Custom User Model
Before Django 1.5 the popular way to customize Django’s built-in User model was to introduce a Profile model with a OneToOne relationship with Django’s built-in User model.
Now it’s possible to do it using inheritance. This recipe will guide you on how to do it for a fresh Django project. While it’s possible to do it for an existing code base, the process is more involved so even if you think you don’t need it at the start of your project it’s a good idea to do this anyway. We hope to write a guide on that in the future.
For this recipe, we’ll use a new Django project named cookbook
.
django-admin.py startproject cookbook
Once inside the generated directory you should see a directory named cookbook/
alongside a file named manage.py
Pretty standard stuff so far.
One thing I like to do is add my Django sub-apps inside the project’s namespace. For our custom User model, let’s put it inside the cookbook.users
namespace. To do that we’ll need to create the cookbook/users/
directory first and then run the usual startapp
command.
mkdir cookbook/users
./manage.py startapp users cookbook/users
Adding cookbook/users
at the end of the startapp
command tells Django to place the boilerplate code there. If it is unspecified, it will show up at the same level as cookbook/
and manage.py
.
Don’t forget to update INSTALLED_APPS
inside cookbook/settings.py
.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cookbook.users',
]
Custom User model that behaves exactly like Django’s builtin User model
Now it’s time to create our custom User model. If you don’t need to customize anything right now, but just want to specify a custom user model you can do so by inheriting from AbstractUser. This effectively gives you everything that’s already in Django’s builtin User model.
from django.contrib.auth.models import AbstractUser
class CookbookUser(AbstractUser):
pass
Custom User model with, well, customizations
For our example, we’ll add created and modified timestamp fields to CookbookUser
using TimeStampedModel from django-extensions.
There is also a TimeStampedModel from django-model-utils. There are pros and cons in choosing one package over the other, but for the purpose of this example both implementations are basically the same. I personally prefer using the implementation from django-extensions, because I also use the other things that come with it.
from django.contrib.auth.models import AbstractUser
from django_extensions.db.models import TimeStampedModel
class CookbookUser(TimeStampedModel, AbstractUser):
pass
It looks the same - which is kind of the point. It’s now possible to specify custom fields and behavior using simple inheritance.
Telling Django to use our User model instead of the default one
At this point our Django project is still using django.contrib.auth.models.User as its user model. We can change this by specifying CookbookUser
as our AUTH_USER_MODEL
inside settings.py
# Custom user model is implemented inside cookbook/users/models.py
AUTH_USER_MODEL = 'users.CookbookUser'
At this point we can finally create the migrations for our new model.
./manage.py makemigrations
We now have our own custom User model. We can add even more changes in the future. This guide aims to teach you enough to have something usable and does not cover all the nuances of using a custom User model as well as the official documentation.
Django Admin
One problem you might run into is unhashed passwords for users created using the admin site.
Your admin.py
for your custom user model might look something like this:
from django.contrib import admin
from .models import CookbookUser
admin.site.register(CookbookUser)
Since we ask Django to automatically create an admin page for CookbookUser
, the code above treats the password field as just another text field so whatever you type in is saved verbatim in the database.
Custom behavior for this admin form was created in UserAdmin
so we can set that as the admin class for our custom user model.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CookbookUser
admin.site.register(CookbookUser, UserAdmin)
If you found this useful and would like to get updates on new posts, please subscribe to our newsletter and follow us on Twitter @DjangoCookbook.