By default, Django uses a built-in User model for authentication. If you’d like a basic tutorial on how to implement login, log out, sign up you can see the Django Authentication SignUpView -LoginView-LogoutView
However, the Django documentation highly recommends using a custom user model for a real-world project. Because this provides far more flexibility. In todays’ article, we will see how to create a custom user model for Django projects.
The default User model in Django uses a username to uniquely identify a user during authentication. We can create a custom Django user model by either subclassing AbstractUser or AbstractBaseUser. The difference is AbstractUser uses the existing fields of the User model and just allows to remove the username field.
On the contrary, AbstractBaseUser is used if one wants to start from scratch by creating completely a new User model. Here we will use AbstractBaseUser
Firstly, we have created a Django project called ‘CUSTOM_AUTHENTICATION’ and an app named ‘custom_auth’. Now we are all set to start our work. So, without further ado let’s create our CustomUser model first.
Custom User Model
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager # Create your models here. class CustomUser(AbstractBaseUser): """ AbstractBaseUser provides core functionalities of a user authenticatin system like password hashing, session storing, recognizing, tokenizing, password reset and and all those functionalities. """ username = models.CharField(max_length=20,unique=True) email = models.EmailField(verbose_name="Email Address", max_length=60, unique=True) phone = models.PositiveIntegerField(null=True,blank=True) date_joined = models.DateTimeField(auto_now_add=True) last_login = models.DateTimeField(verbose_name='last login', auto_now= True) is_admin = models.BooleanField(default=False) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) # this constant defines which field # will be used as username as login credential USERNAME_FIELD = "email" REQUIRED_FIELDS = ['username',] # This manager will take care of each # object of this model before creation objects = CustomUserManager() def __str__(self): return self.username def has_perm(self, perm, obj=None): return True def has_module_perms(self, app_label): return True
settings.py we’ll register the
'custom_auth' app in
INSTALLED_APPS and use the
AUTH_USER_MODEL config to tell Django to use our new
CustomUser model in place of the built-in
AUTH_USER_MODEL = 'custom_auth.CustomUser' # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # my apps 'custom_auth', ]
Here we have Created a new class called CustomUser that subclasses AbstractBaseUser and Added fields for email, username, phone, is_staff, is_active, is_admin, is_superuser, and date_joined and last_login. Though both email and username are unique fields, we will user email as our username field. So, we will have to set the USERNAME_FIELD to email.
Then we have Specified that all objects for the class come from the CustomUserManager We will create this now.
Custom User Manager
The CustomUserManager will be subclassing BaseUserManager. It uses an email as the unique identifier instead of a username. We can place CustomUserManager inside a managers.py file in the “custom_user” directory or we can place it inside models.py but it must be placed before the model.
class CustomUserManager(BaseUserManager): def create_user(self, email, username, phone=None, password=None): if not email: raise ValueError('Email is required') if not username: raise ValueError('Username is required') if not password: raise ValueError("Password is required") # create user object user = self.model( email=self.normalize_email(email), username = username, phone = phone, ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, username, password=None): user = self.create_user( email=self.normalize_email(email), username=username, password=password, ) user.is_admin = True user.is_staff = True user.is_superuser = True user.save(using=self._db) return user
Everything is set to run migrations. After running migrations, we will have our CustomUser table in our database. But we will have to register it on admin site for getting a visual representation. Let’s register it on the admin site.
from django.contrib import admin from .models import CustomUser # Register your models here. class CustomUserAdmin(admin.ModelAdmin): list_display = ['email', 'username', 'is_active'] admin.site.register(CustomUser, CustomUserAdmin)
Still, we don’t have any CustomUser object. We will create a super user first by running this command… (Virtual Environment must be activated)
python manage.py createsuperuser
We must give the required credentials.
(env) PS E:\Django\project\custom_authentication> python manage.py createsuperuser Email Address: email@example.com Username: admin Password: Password (again): The password is too similar to the username. This password is too short. It must contain at least 8 characters. This password is too common. Bypass password validation and create user anyway? [y/N]: y Superuser created successfully.
Django created a Superuser (admin) successfully. Let’s run the server and log in to the Django admin panel.
Add New User