Ответ
В 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.
Ответ 18+ 🔞
А, вот и ты, мой друг! Сидишь, значит, и думаешь: "Как бы мне эту стандартную модель User в Django так по-взрослому переделать, чтобы и функционал был, и в жопу не вылететь?" Понимаю, понимаю. Сейчас разложу тебе всё по полочкам, как есть, без прикрас и этой вашей академической зауми.
Слушай сюда, их всего четыре, этих подхода. Как четыре стихии, блядь. Выбирай по ситуации, а то потом будешь как Герасим — молчать и страдать, потому что не ту модель выбрал.
1. Proxy-модель (она же — "хитрая жопа")
Это когда тебе поля в базе менять не надо, но очень хочется, чтобы у твоего юзера были какие-то новые методы или менеджер кастомный. Типа, добавить ему метод get_full_name_and_email, чтобы красиво выводилось. Всё делается легко, миграций не требует — просто объявил и пользуешься.
Когда брать: Когда тебе просто поведение поменять, а структуру данных не трогать. Как будто ты надел на стандартного юзера новый костюм, а под ним всё тот же труселя.
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 связь (она же — "профиль пользователя")
Классика жанра, ёпта! Все так делали, когда Django только начинал. Берёшь стандартного User и пристёгиваешь к нему отдельную модельку Profile через связь "один к одному". Туда все доп. поля и пихаешь: аватарку, дату рождения, "о себе".
Преимущество: Не лезешь в святая святых — в саму модель юзера. Добавил поле, удалил поле — и ни у кого не сломалось. Идеально для ленивых и осторожных.
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 и говоришь: "Папа, я буду как ты, но с татухой". То есть наследуешься и добавляешь свои поля прямо в ту же таблицу в базе. Телефон добавить? Пожалуйста. Отчество? Да хуй с ним, добавляй!
Важный момент, блядь! После того как создал такую модель, надо в settings.py прописать: AUTH_USER_MODEL = 'yourapp.CustomUser'. Иначе Django будет искать своего родного юзера, а найдёт твоего ублюдка и обосрётся.
# 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) # Вот, поле добавил
# А это вот — магические строчки, чтобы не было конфликтов с группами и пермишенами. Без них может быть больно.
groups = models.ManyToManyField('auth.Group', related_name='customuser_set', blank=True)
user_permissions = models.ManyToManyField('auth.Permission', related_name='customuser_set', blank=True)
4. Наследование от AbstractBaseUser (она же — "я сам с усами")
А это, дружок, полный разгон и максимальная гибкость. Ты говоришь стандартному юзеру: "Пошёл на хуй, я всё сделаю сам!" Создаёшь модель практически с нуля. Хочешь, чтобы логин был по email, а не по username? Легко! Хочешь убрать поле first_name? Да пожалуйста!
Когда брать: Когда у тебя специфичные требования к аутентификации или тебе реально надо перелопатить всё. Но будь готов — это овердохуища работы. Ты сам становишься ответственным за create_user, create_superuser и прочую базовую хуйню.
# 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' # Говорим Django: "Смотри, друг, логин у меня теперь email!"
REQUIRED_FIELDS = [] # А тут можно указать, какие поля ещё спрашивать при createsuperuser
И её тоже в settings.py прописать не забудь! AUTH_USER_MODEL = 'yourapp.MyUser'.
Вот и весь расклад, блядь. Выбирай с умом, не торопись. А то потом будешь как тот мудак Герасим — смотреть на утопленную Муму и понимать, что всё пошло по пизде. Удачи!