Creating a custom user model in django
NOTE 1 - Prerequisite to this project is here, first - understand the basics.
NOTE 2 - This is basically a copy of https://learndjango.com/tutorials/django-custom-user-model tutorial. Wanted to keep a copy of it for myself, since this information is useful.
NOTE 3: for me this post is just a reference of how it can be done IF NOT using django's "allauth" package. If using "allauth" - I still have not figured out how to implement custom fields to the user model.
But if not using "allauth package" - this tutorial will help you out.
Django ships with a built-in User model for authentication.
However, for a real-world project, the official Django documentation highly recommends using a custom user model instead; it provides far more flexibility down the line so, as a general rule
always use a custom user model for all new Django projects
There are two modern ways to create a custom user model in Django:
AbstractUser
and AbstractBaseUser
. In both cases, we can subclass them to
extend existing functionality; however, AbstractBaseUser
requires much,
much more work. Seriously, only mess with it if you know what you're doing.
And if you did, you wouldn't be reading this tutorial, would you?
So we'll use AbstractUser
, which subclasses AbstractBaseUser
but provides
more default configuration.
Creating our initial custom user model requires four steps:
- update
django_project/settings.py
- create a new
CustomUser
model - create new
UserCreation
andUserChangeForm
forms - update the admin
In settings.py
, we'll use the AUTH_USER_MODEL
config to tell Django to use
our new custom user model instead of the built-in User
model. We'll call our
custom user model CustomUser
.
# project/settings.py AUTH_USER_MODEL = "accounts.CustomUser" # new
Now update accounts/models.py
with a new User model, which we'll call
CustomUser
.
"""A module to register account app models to django admin.""" from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): """Account model.""" date_of_birth = models.DateField(null=True, blank=True) # add additional fields in here
We need new versions of two form methods that receive heavy use working with
users. Create a new file accounts/forms.py
. We'll update it with the
following code to largely subclass the existing forms.
# accounts/forms.py """A module for auth page forms. They are later used in the views.py""" from django import forms from django.contrib.auth.forms import UserChangeForm, UserCreationForm from apps.accounts.models import CustomUser # pylint: disable=too-few-public-methods class CustomUserCreationForm(UserCreationForm): """A form for user creation""" class Meta: """Additional settings for the Meta?""" model = CustomUser fields = ("username", "email", "date_of_birth") date_of_birth = forms.DateField( widget=forms.DateInput(attrs={"type": "date"}), ) # pylint: disable=too-few-public-methods class CustomUserChangeForm(UserChangeForm): """A form for user change""" class Meta: """Additional settings for the Meta?""" model = CustomUser fields = ("username", "email", "date_of_birth") date_of_birth = forms.DateField( widget=forms.DateInput(attrs={"type": "date"}), )
Finally, we update admin.py
since the admin is highly coupled to the default
User model.
# accounts/admin.py """A module to register users app models to django admin.""" from django.contrib import admin from django.contrib.auth.admin import UserAdmin from apps.accounts.forms import CustomUserChangeForm, CustomUserCreationForm from apps.accounts.models import CustomUser class CustomUserAdmin(UserAdmin): """A modification to the default account model admin.""" add_form = CustomUserCreationForm form = CustomUserChangeForm model = CustomUser fieldsets = ( (None, {"fields": ("username", "password")}), ( "Personal info", {"fields": ("first_name", "last_name", "email", "date_of_birth")}, ), ( "Permissions", { "fields": ( "is_active", "is_staff", "is_superuser", "groups", "user_permissions", ) }, ), ("Important dates", {"fields": ("last_login", "date_joined")}), ) list_display = [ "email", "username", "date_of_birth", ] admin.site.register(CustomUser, CustomUserAdmin)
And we're done! We can now run makemigrations
and migrate
(clear the db and
migrations if you are doing makemigrations not for the first time, we need to
start fresh here) to create a new database that uses the custom user model.
python manage.py makemigrations accounts python manage.py migrate
The last step is our views.py
file in the accounts
app which will contain
our signup form. We will modify the already created form.
"""A module for accounts app views.""" from django.contrib.auth.decorators import login_required from django.shortcuts import render from django.urls import reverse_lazy from django.views.generic import CreateView from apps.accounts.forms import CustomUserCreationForm class SignUpView(CreateView): """Generic CBV view for account create page""" form_class = CustomUserCreationForm success_url = reverse_lazy("login") template_name = "registration/signup.html"