Blog Details

Custom User Models in Django: Tailoring Authentication to Your Needs
Prajwal Kamde

Prajwal Kamde

26 Aug 2024

Custom User Models in Django: Tailoring Authentication to Your Needs

Django is a powerful web framework that offers a built-in User model to handle authentication and user management out of the box. However, many projects require additional user attributes or behaviors that aren't accommodated by Django's default User model. This is where custom user models come into play. Custom user models allow you to tailor the authentication system to fit the specific needs of your application. In this blog, we’ll explore the concept of custom user models in Django, the different types of custom user models, and provide examples for each.

Understanding Django’s Default User Model

Django’s default User model, located in django.contrib.auth.models.User, includes fields for basic user attributes like username, password, email, first name, and last name. While this model works well for many applications, it’s often necessary to extend or replace it to meet specific requirements.

Why Use a Custom User Model?

There are several reasons to use a custom user model:

  1. Additional Fields: You may need to store additional information about users that isn’t included in the default model, such as profile pictures, addresses, or birthdates.
  2. Custom Authentication Logic: Your application might require custom authentication methods or user behaviors.
  3. Different User Types: In some cases, you might need to manage different types of users with different attributes or permissions.

Types of Custom User Models

Django provides several ways to create custom user models. Here are the most common approaches:

1. Extending the AbstractUser Model

The AbstractUser class is a good starting point for customizing the default User model. It includes all the fields and methods from the default User model but allows you to add your own fields and methods.

Example:

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
   # Add custom fields
   profile_picture = models.ImageField(upload_to='profile_pictures/', null=True, blank=True)
   birthdate = models.DateField(null=True, blank=True)

   def __str__(self):
       return self.username
 

How to Use:

  1. 1. Define your custom user model by extending AbstractUser.
  2. 2. Set AUTH_USER_MODEL in your settings to point to your custom model:
  3.  
  4. AUTH_USER_MODEL = 'myapp.CustomUser'
  5.  
  6. 3. Run migrations to apply the changes:
  7.  
  8. python manage.py makemigrations
    python manage.py migrate
     
  9. 2. Extending AbstractBaseUser

  10. For more extensive customizations, including different user authentication schemes, you can extend AbstractBaseUser. This approach requires more setup but offers greater flexibility.
  11. Example:
  12. from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
    from django.db import models
    from django.utils import timezone
  13.  
  14. 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
  15.    def create_superuser(self, email, password=None, **extra_fields):
           extra_fields.setdefault('is_staff', True)
           extra_fields.setdefault('is_superuser', True)
           return self.create_user(email, password, **extra_fields)
  16.  
  17. class CustomUser(AbstractBaseUser):
       email = models.EmailField(unique=True)
       is_active = models.BooleanField(default=True)
       is_staff = models.BooleanField(default=False)
       # Add custom fields
       profile_picture = models.ImageField(upload_to='profile_pictures/', null=True, blank=True)
       birthdate = models.DateField(null=True, blank=True)
  18.    objects = CustomUserManager()
  19.    USERNAME_FIELD = 'email'
       REQUIRED_FIELDS = []
  20.  
  21.    def __str__(self):
           return self.email
     
  22. How to Use:
  23. Define your custom user model by extending AbstractBaseUser and implement the required methods.
  24. Create a custom manager by extending BaseUserManager.
  25. Set AUTH_USER_MODEL in your settings to point to your custom model.
  26. Define USERNAME_FIELD and REQUIRED_FIELDS in your model.
  27. Run migrations to apply the changes.
  28. 3. Profile Model with One-to-One Link

  29. Sometimes you might prefer to keep Django’s default User model but need to add additional information. In this case, you can use a separate profile model with a one-to-one relationship to the default User model.
  30. Example:
  31.  
  32. from django.conf import settings
    from django.db import models
  33.  
  34. class UserProfile(models.Model):
       user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
       profile_picture = models.ImageField(upload_to='profile_pictures/', null=True, blank=True)
       birthdate = models.DateField(null=True, blank=True)
  35.  
  36.    def __str__(self):
           return self.user.username

    How to Use:
  37. 1. Create a separate profile model with a one-to-one field linking to the default User model.
  38. 2. Use Django signals to automatically create or update the user profile when a user is created or updated.

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from .models import UserProfile

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance, created, **kwargs):
   if created:
       UserProfile.objects.create(user=instance)

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def save_user_profile(sender, instance, **kwargs):
   instance.userprofile.save()
 

Conclusion

Custom user models in Django provide the flexibility needed to tailor user authentication and management to your specific needs. Whether you choose to extend the AbstractUser or AbstractBaseUser models or use a profile model to supplement the default User model, Django’s customization options allow you to design an authentication system that aligns with your application’s requirements.

By leveraging these custom user models, you can enhance your application’s user experience, add additional attributes, and implement custom behaviors, paving the way for more robust and user-centric features in your Django projects.