How to Extend Django User Model using AbstractBaseUser

Django, a high-level Python web framework, provides a robust User model for authentication and user management. However, many projects require extending the default User model to accommodate additional user-specific attributes and behaviors. In this blog, we’ll explore the method of extending Django User Model using AbstractBaseUser and walk through a detailed example.

Understanding AbstractBaseUser

The AbstractBaseUser class is a powerful foundation for creating a custom User model in Django. Unlike AbstractUser, which provides a more straightforward approach by extending the existing User model, AbstractBaseUser allows you to create a user model from scratch while customizing authentication methods and fields.

Read More on Extending the Django User Model: Exploring Various Approaches

Benefits of Using AbstractBaseUser

  • Customization: With AbstractBaseUser, you can implement authentication methods tailored to your application’s needs.
  • Flexibility: You have complete control over fields, allowing you to create a User model that aligns with your project’s requirements.
  • Scalability: As your project grows, you can easily add or modify fields and methods.

Step-by-Step Implementation

Let’s dive into the process of extending Django User Model using AbstractBaseUser with an example of creating a CustomUser model.

Note: We have create a already created our django project using using our blog on Django Basic Template Boilerplate Skeleton Project. For this example, we have created a app named “accounts“.

Step 1: Create a Custom User Manager

# accounts/models.py

from django.contrib.auth.models import BaseUserManager

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

    def create_superuser(self, email, username, 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, username, password, **extra_fields)

Step 2: Create the Custom User Model

# accounts/models.py

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=30, unique=True)
    bio = models.TextField(max_length=500, blank=True)
    profile_picture = models.ImageField(upload_to='profile_pics/', blank=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def __str__(self):
        return self.username

Step 3: Update Settings

In your project’s settings.py, specify your custom User model:

AUTH_USER_MODEL = 'your_app.CustomUser'

Step 4: Applying Migrations

Run the following commands to apply migrations and create the custom User model:

python manage.py makemigrations
python manage.py migrate

Conclusion

Extending the Django User Model using the AbstractBaseUser method offers unparalleled customization and control over your application’s authentication and user management. By following the step-by-step example in this blog, you’ve learned how to create a CustomUser model with unique fields and authentication logic. This approach empowers you to build applications that go beyond the default User model while maintaining security and scalability. As you explore Django’s capabilities further, remember that selecting the right extension method depends on the complexity and goals of your project.

Find this project on Github.

Blogs You Might Like to Read!