Sobes.tech
Middle

What are the ways to define a user model in Django?

sobes.tech AI

Answer from AI

The user model in Django is defined by the AUTH_USER_MODEL setting. The following options are possible:

  1. Using the built-in django.contrib.auth.models.User model.
  2. Inheriting from AbstractUser and creating your own model.
  3. Inheriting from AbstractBaseUser and creating your own model.
Method Description When to use
django.contrib.auth.models.User Standard, ready-to-use model. In most cases, when the standard fields are sufficient.
AbstractUser Extending the built-in model with additional or modified functionality. When you need to add fields to the standard ones (e.g., phone_number).
AbstractBaseUser Fully custom user model with minimal base. When flexibility is needed, for example, to use email instead of username for authentication.

Example of using AbstractUser:

# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
# myapp/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    # Additional fields
    phone_number = models.CharField(max_length=15, blank=True)
    # Override AbstractUser fields if necessary

    class Meta:
        verbose_name = 'User'
        verbose_name_plural = 'Users'

Example of using AbstractBaseUser:

# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
# myapp/models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None):
        if not email:
            raise ValueError('Users must have an email address')
        user = self.model(email=self.normalize_email(email))
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None):
        user = self.create_user(email, password=password)
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)  # Using email as the unique identifier
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    date_joined = models.DateTimeField(auto_now_add=True)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'  # Set email as the login identifier
    REQUIRED_FIELDS = [] # Required fields when creating a superuser

    def __str__(self):
        return self.email

    # Methods required by PermissionsMixin
    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    class Meta:
        verbose_name = 'User'
        verbose_name_plural = 'Users'

It is important to define AUTH_USER_MODEL early in development, before running migrations. Changing it after migrations are applied requires more complex data migration steps.