Django; Customizing Built-in User Model
By: Farid Mv
Tags: Authentication, Customization, User Model, Django, Python

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/