How to create a Custom User in Django

This tutorial will teach how to create a custom user in Django.

Django comes with good authentication, which uses a username and password, but sometimes one is unsatisfied with what Django offers. You might want to change the way users login into your system, such as using email and password, here you will have to create a custom user model to gather for your needs.

Ways you can create a custom user model

Extending the existing user model

Extending the existing user depends on two things:

  • If the changes you are trying to make are behavioral and don’t require any modification in what appears in the database, here you can use a proxy model. A proxy model creates inheritance without creating a new table in the database. For example, changing the default ordering style, this doesn’t create any new tables.
  • If the changes you are trying to make will affect the behavior of the database, such as having a user and a profile section. Here you can use a OneToOneField so that you will be in a position to create only one relationship to each field. Here are trying to store extra information about the user but it doesn’t relate in any way to the authentication process.

Substituting a custom user model

In some instances, it’s better to use an email address to authenticate users instead of a username. Django allows overriding the default User model by providing AUTH_USER_MODEL that reference to the custom user. This is done in the settings.

AUTH_USER_MODEL = 'accounts.CustomUser'

It’s highly recommended to set up the custom user model at the beginning stage of initiating the project to avoid creating conflicts with foreign keys created in the database. If this happens you will have to re-engineer the database to avoid losing precious data. So do it before that first migration.

Extending AbstractUser

You use this method when you are satisfied with how Django handles the authentication process, your aim is only to add information directly to the user model without creating an extra class.

Extending AbstractBaseUser

Here a new user inherits from the AbstractBaseUser subclass. Use this option if you’re creating a new user entirely. You use it whenever you have specific requirements in relation to authentication. For example, I will prefer to get an authentication token via email.

To make it easy to include Django’s permissions framework, you will have to consider using permissionsMixin because it gives you methods and database fields necessary to support Django’s permission model.

The easiest way to construct a compliant custom user model is to inherit from AbstractBaseUser. AbstractBaseUser provides the core implementation of a user model, including hashed passwords and tokenized password resets.

Steps to follow

1. Create Django project

To start, create a Django project with this article How to set up a Python Django Application using Django 4.0

After you are done setting up the Django project, we can proceed to create the user.

2. Create a custom user by extending AbstractBaseUser

Go to models in your app and use the following code snippet to create a manager.

# models.py
from django.db import models
from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin

class CustomUserManager(BaseUserManager):

    """
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """

    def createUser(self, email, username, password, **extra_fields):
        """
        Create and save a User with the given email and password.
        """
        if not email:
            raise ValueError("Provide an email address")

        email=self.normalize_email(email)
        user=self.model(email=email, username=username, **extra_fields)

        user.set_password(password)

        user.save()

        return user

    def create_superuser(self, email, username, 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_staff=True.'")

        return self.createUser(email, username, password, **extra_fields)

The next thing is to create a custom user class. Use the following snippet

# models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.CharField(max_length=50, unique=True)
    username = models.CharField(max_length=100, unique=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_created = models.DateTimeField(auto_now_add=True)
    phone_number = PhoneField(blank=True, help_text='Contact phone number')
    user_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True)
    
    objects = CustomUserManager()
    USERNAME_FIELD='email'
    REQUIRED_FIELDS=['username', 'phone_number']

    def __str__(self):
        return self.username

Head over to settings.py and add AUTH_USER_MODEL='accounts.CustomUser'

From here, you can run migrations and createsuperuser to test with. At this point, you can now continue working on extending the project.

I hope you enjoy it.

About Mason Kipward

I am a technology enthusiast who loves to share gained knowledge through offering daily tips as a way of empowering others. I am fan of Linux and all other things open source.
View all posts by Mason Kipward →

Leave a Reply

Your email address will not be published. Required fields are marked *