Django; Customizing Built-in User Model

Farid Mv
3 min readDec 24, 2020

In this very short story I want to tell you how you can customize the built-in Django’s User Model and how you can have a customized username using Regex (Regular Expression).

I assume you know the basics of Python and Django, so I just start the step by step stages of customizing the Django’s User Model from “django.contrib.auth.models”.

The python and Django version for the sample codes in this story are:

  • Python 3.9.1
  • Django 3.1.4

Step 1:

So first start with the “models.py” file in one of the apps of your project. Lets say our app here is “myapp”.

Then in in this file you need to define two classes:

  • MyUser
  • MyUserManager

Actually these are two names that you decide, so you can choose what ever name you want.

Here is the sample code for these two classes in file “myapp.models.py”:

from django.contrib.auth.models import AbstractUser, UserManager
from django.core import validators
from django.db import models


class MyUserManager(UserManager):

def create_user(self, username, password=None):
user = self.model(
username=username,
)

user.set_password(password)
user.save(using=self._db)
return user

def create_superuser(self, username, email=None, password=None):
user = self.create_user(
username,
password=password,
)
user.is_admin = True
user.is_superuser = True
user.is_staff = True
user.email = email.lower()
user.save(using=self._db)
return user


class MyUser(AbstractUser):
username = models.CharField(verbose_name='Username', name='username', max_length=30, unique=True,
validators=[
validators.RegexValidator(regex=r'^(?!_)(?!.*\.\.)(?!.*\.$)[a-z0-9][a-z0-9.]{4,29}$',
message='Valid Characters: Lowercase Alphanumeric and a Dot(.)',
code='Invalid username'),
validators.MinLengthValidator(limit_value=5)
],
error_messages={'unique': 'A user with that username already exists.',
'invalid': 'Valid Characters: Lowercase Alphanumeric and at most one Underscore(_)'})
objects = MyUserManager()

In this example we are going to accept usernames that are only lowercase alphanumeric characters and dots. you can change the regex and accept what ever pattern you would like.

Ok, in “MyUser” class which inherits from “AbstractUser” class from the package “django.contrib.auth.models” you can define what ever field you want to have for your user model.

in the “MyUserManager” class which inherits from “UserManager” class form the package “django.contrib.auth.models” you should define two methods.

  • The “create_user” for the signups of frontend users.
  • The “create_superuser” for the staff and admin users.

Again these two methods you can do what ever validations and procedures you want to do, but this code that I have provided to you here is the basic code that you should have.

If you don’t define the “MyUserManager” you might get the following error:

Manager isn’t available; ‘auth.User’ has been swapped for ‘myapp.MyUser’

Step 2:

Next you should tell to Django that you want to user “myapp.MyUser” instead of the built-in Django’s User Model. So you should add the following line to you “settings.py”:

AUTH_USER_MODEL = 'myapp.MyUser'

Step 3:

To link your customized “MyUser” user model with the signup form you should link “UserCreationForm” from package “django.contrib.auth.forms” with your signup view. Here is a sample code for that:

from django.contrib.auth import authenticate, login
from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.views import generic
from django.contrib.auth.forms import UserCreationForm
from django.views import View

from myapp.models import MyUser
class MyUserCreationForm(UserCreationForm):
class Meta:
model = MyUser
fields = ('username', 'password1', 'password2',)


class SignUp(generic.CreateView):
form_class = MyUserCreationForm
success_url = reverse_lazy('home')
template_name = 'myapp/signup.html'

def post(self, request):
if request.user.is_authenticated:
return redirect('home')

form = MyUserCreationForm(request.POST)

if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect(self.success_url)

ctx = {'form': form}
return render(request, self.template_name, ctx)

def get(self, request):
if request.user.is_authenticated:
return redirect('home')

form = MyUserCreationForm()
ctx = {'form': form}
return render(request, self.template_name, ctx)

I must emphasize that to link your signup form to your customized user model you should define “MyUserCreationForm” and inherit “UserCreationForm” from the package “django.contrib.auth.forms”. The name of the class you define is arbitrary and you can choose what ever name you would like to use.

In your signup view you should use the “MyUserCreationForm” as the form class and pass this to your template to populate your signup form.

The source code for this tutorial is here:

https://github.com/faridmv/DjangoCustomUserModel

And that’s it you successfully customized your user model. If you want to have control on your users in the “Admin” panel you have do some other coding that you can read about them in the Django documentation link that is provided here.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

for more information you can read the Django documentation about “Customizing authentication in Django” at the following link:

https://docs.djangoproject.com/en/3.1/topics/auth/customizing/

--

--