Какие существуют способы расширения стандартной модели пользователя в Django?

«Какие существуют способы расширения стандартной модели пользователя в Django?» — вопрос из категории Django, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Django существует четыре основных подхода для кастомизации стандартной модели User, каждый из которых подходит для разных задач.

1. Proxy-модель

Используется, когда нужно изменить поведение модели (например, добавить новые методы или изменить стандартный менеджер), но не требуется добавлять новые поля в базу данных.

  • Преимущества: Простота реализации, не требует миграций схемы БД.
  • Сценарий: Добавить метод get_full_name() или кастомный менеджер для фильтрации пользователей.
from django.contrib.auth.models import User

class CustomUserManager(models.Manager):
    def get_staff_users(self):
        return self.get_queryset().filter(is_staff=True)

class StaffUser(User):
    objects = CustomUserManager()

    class Meta:
        proxy = True
        ordering = ('first_name',)

    def get_full_name_and_email(self):
        return f"{self.first_name} {self.last_name} <{self.email}>"

2. One-to-One связь (Профиль пользователя)

Классический способ добавить дополнительные поля, не затрагивая исходную модель User. Создается отдельная модель (например, Profile), связанная с User отношением «один к одному».

  • Преимущества: Не изменяет ядро Django, легко добавлять и удалять поля.
  • Сценарий: Хранение аватара, биографии, даты рождения.
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    bio = models.TextField(blank=True)
    birth_date = models.DateField(null=True, blank=True)

3. Наследование от AbstractUser

Этот подход позволяет добавить поля непосредственно в таблицу пользователей, унаследовав все поля и методы стандартного User.

  • Преимущества: Все данные пользователя хранятся в одной таблице.
  • Сценарий: Добавить поле phone_number или patronymic как обязательное.
# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    phone_number = models.CharField(max_length=20, blank=True)
    # Добавляем related_name, чтобы избежать конфликтов
    groups = models.ManyToManyField('auth.Group', related_name='customuser_set', blank=True)
    user_permissions = models.ManyToManyField('auth.Permission', related_name='customuser_set', blank=True)

Важно: После создания такой модели необходимо указать ее в settings.py: AUTH_USER_MODEL = 'yourapp.CustomUser'

4. Наследование от AbstractBaseUser

Обеспечивает максимальную гибкость. Вы создаете модель пользователя с нуля, определяя только самые базовые поля и методы для аутентификации (например, get_full_name, get_short_name).

  • Преимущества: Полный контроль над моделью, включая механизм аутентификации (например, логин по email вместо username).
  • Сценарий: Создание системы, где email является основным идентификатором.
# models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class MyUserManager(BaseUserManager):
    # ... реализация create_user и create_superuser

class MyUser(AbstractBaseUser):
    email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

Также требует регистрации в settings.py через AUTH_USER_MODEL.