Extending or Replacing the Default User Model in Django


Django provides a built-in User model for authentication and user management. However, you may need to customize it to add extra fields or functionality. This article covers how to extend or replace the default user model in Django with examples.

1. Why Extend or Replace the User Model?

The default Django User model includes fields like username, email, and password. If you need additional fields (e.g., date of birth, profile picture) or wish to remove unused fields, you can either extend or replace the model.

2. Extending the Default User Model

You can extend the default user model using a One-to-One relationship. This approach allows you to add extra fields without modifying the existing model.

Example: Extending with a Profile Model

            
    # models.py
    from django.contrib.auth.models import User
    from django.db import models

    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        date_of_birth = models.DateField(null=True, blank=True)
        profile_picture = models.ImageField(upload_to='profiles/', null=True, blank=True)

        def __str__(self):
            return self.user.username
            
        

Connect the Profile model to the User model using Django signals:

            
    # signals.py
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    from django.contrib.auth.models import User
    from .models import Profile

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

    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        instance.profile.save()
            
        

Don't forget to register the signals:

            
    # apps.py
    from django.apps import AppConfig

    class MyAppConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        name = 'myapp'

        def ready(self):
            import myapp.signals
            
        

3. Replacing the Default User Model

Replacing the default user model is a more flexible approach but requires careful planning because it must be done at the start of the project.

Steps to Replace the Default User Model

Define a custom user model by subclassing AbstractUser or AbstractBaseUser.

Example: Using AbstractUser

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

    class CustomUser(AbstractUser):
        date_of_birth = models.DateField(null=True, blank=True)
        profile_picture = models.ImageField(upload_to='profiles/', null=True, blank=True)
            
        

Update settings.py

Set the AUTH_USER_MODEL to point to your custom user model:

            
    # settings.py
    AUTH_USER_MODEL = 'myapp.CustomUser'
            
        

Migrate Changes

Run migrations to apply the changes:

            
    python manage.py makemigrations
    python manage.py migrate
            
        

Example: Using AbstractBaseUser

For full control over the user model, subclass AbstractBaseUser and implement your own fields and methods:

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

    class CustomUserManager(BaseUserManager):
        def create_user(self, email, password=None, **extra_fields):
            if not email:
                raise ValueError("The Email field is required")
            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)
            return self.create_user(email, password, **extra_fields)

    class CustomUser(AbstractBaseUser):
        email = models.EmailField(unique=True)
        date_of_birth = models.DateField(null=True, blank=True)
        is_active = models.BooleanField(default=True)
        is_staff = models.BooleanField(default=False)

        objects = CustomUserManager()

        USERNAME_FIELD = 'email'
        REQUIRED_FIELDS = []
            
        

Update Admin Interface

Customize the admin interface for the custom user model:

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

    class CustomUserAdmin(UserAdmin):
        model = CustomUser
        fieldsets = UserAdmin.fieldsets + (
            (None, {'fields': ('date_of_birth',)}),
        )

    admin.site.register(CustomUser, CustomUserAdmin)
            
        

4. Choosing the Right Approach

Use the Profile Model approach for simple extensions and Custom User Model if you need full customization.

5. Conclusion

Extending or replacing the default user model in Django allows you to customize user management according to your application's requirements. Plan your approach carefully, especially when replacing the user model, as it affects the entire project.





Advertisement