Custom User Model with Email Authentication

Posted: September 10, 2024 | Updated: September 14, 2024

Django highly recommends that users create a custom user model when they build an app. If you attempt to do this later, it will involve a lot of work, and migrating existing data will be time-consuming and complicated.

How to Create a Custom User Model with Email Authentication in Django

Step 1: Create an app named "accounts"

python manage.py startapp accounts

Step 2: Then add that app in your main app settings.py file.

INSTALLED_APPS = [
   'accounts',
]

Step 3: Define the Custom User Model: In your accounts/models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
from django.utils import timezone


class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('The Email field must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', 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_superuser=True.')

        return self.create_user(email, password, **extra_fields)

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=30, blank=True)
    last_name = models.CharField(max_length=30, blank=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    date_joined = models.DateTimeField(default=timezone.now, editable=False)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.email

Step 4: Update settings to use the custom user model

 In your main app settings.py file, add the following code.

AUTH_USER_MODEL = 'accounts.CustomUser'

Step 5: Migrate the changes

Create and apply migrations:

python manage.py makemigrations
python manage.py migrate

Step 6: Update admin to handle the custom user model

In accounts/admin.py add the following code.

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

class CustomUserAdmin(UserAdmin):
    model = CustomUser
    list_display = ['email', 'first_name', 'last_name', 'is_staff']
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('first_name', 'last_name')}),
        ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser')}),
        ('Important dates', {'fields': ('last_login',)}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    readonly_fields = ('date_joined',)  # Make 'date_joined' read-only


admin.site.register(CustomUser, CustomUserAdmin)

Step 7: Create an admin account using email and password

py manage.py createsuperuser

Step 8; Test the Admin login

Now run the development server and try logging into your app admin using your email and password.

python manage.py runserver

If it works, then the Custom user model works perfectly. 

© 2024 Webapptiv. All rights reserved.