Стандартная модель пользователя User весьма полезна, но иногда нам нужно настраивать её под конкретные требования приложения.
Разработчики начали задаваться вопросами: "Погодите-ка, а как добавить поле date_of_birth для пользователя?", "А можно сразу хранить номер телефона или картинку профиля?". Встроенная модель User гибкая, но не безграничная. Она имеет фиксированный набор полей (username, email, first_name, last_name, и т.д.), и если нам нужно что-то сверх этого, то потребуется её настроить. Примеров, когда это нужно, масса: социальные сети, интернет-магазины, сайты бронирования и многое другое.
Django предлагает два подхода: расширение модели через One-to-One связь и создание кастомной модели пользователя. Давайте разберём оба варианта.
1. Стандартная модель User
Давайте сначала вспомним, что из себя представляет стандартная модель пользователя в Django. Она уже подключена к нашему проекту и готова к использованию. Вот базовые поля этой модели:
| Поле | Описание |
|---|---|
| username | Имя пользователя (обязательное) |
| Адрес электронной почты | |
| first_name | Имя |
| last_name | Фамилия |
| is_staff | Может ли пользователь входить в админку |
| is_active | Активен ли пользователь |
| date_joined | Дата регистрации |
Вы можете использовать эту модель "из коробки". Например:
from django.contrib.auth.models import User
# Создадим пользователя
user = User.objects.create_user(username='john_doe', email='john@example.com', password='securepassword123')
print(user.username) # john_doe
print(user.email) # john@example.com
Но вот проблема: если вы захотите добавить, скажем, поле phone_number, стандартная модель не позволит это сделать. Что же делать? Расширять!
2. Расширение модели через One-to-One связь
Самый простой способ добавить пользовательские данные — создать дополнительную модель, связанную с моделью User через One-to-One связь. Представьте это как расширение стандартной модели, не ломая её. Этот подход удобен, если у вас уже есть проект, активно использующий стандартную модель User, и вы хотите добавить дополнительные поля.
Пример кода
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=15, blank=True, null=True)
date_of_birth = models.DateField(blank=True, null=True)
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
def __str__(self):
return f"{self.user.username}'s profile"
Теперь мы можем хранить дополнительные данные в модели Profile!
Зачем делать всё вручную, если можно автоматику? Создадим сигнал, который автоматически создаёт Profile при создании User.
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
@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()
Теперь, каждый раз при создании пользователя, будет автоматически создаваться профиль:
user = User.objects.create_user(username='jane_doe', email='jane@example.com', password='supersecurepassword')
print(user.profile) # <Profile: jane_doe's profile>
И вот мы можем получить доступ к дополнительным данным пользователя:
profile = user.profile
profile.phone_number = "+123456789"
profile.save()
3. Создание кастомной модели пользователя
Иногда One-to-One связь недостаточна. Например, вы хотите полностью заменить стандартную модель или изменить поведение полей (например, сделать поле email уникальным и обязательным). Тогда за дело берётся кастомизация модели пользователя.
Когда выбрать кастомную модель?
- Если изменения критичны для всей системы (например,
emailкак уникальный идентификатор пользователя). - Если проект только начинается (так проще).
- Если вы хотите полный контроль над моделью пользователя.
Пошаговая кастомизация
1. Создание кастомного пользователя
Создадим свою модель, унаследованную от AbstractBaseUser (или AbstractUser, если хотим использовать стандартные методы и поведение).
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("У пользователя должен быть email")
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)
full_name = models.CharField(max_length=150)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name']
def __str__(self):
return self.email
2 Регистрация модели в settings.py
После создания кастомной модели нам нужно сообщить Django, что теперь мы используем её:
# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
3 Миграция структуры базы данных
После изменений нужно сделать миграции:
python manage.py makemigrations
python manage.py migrate
4. Использование кастомной модели
Теперь ваша кастомная модель полностью интегрирована. Например:
from myapp.models import CustomUser
user = CustomUser.objects.create_user(email='custom@example.com', password='mypassword', full_name='Custom User')
print(user.email) # custom@example.com
Особенности и типичные ошибки
При расширении через One-to-One связь часто забывают добавить сигналы для создания профиля, что приводит к ошибке
Profile matching query does not exist.При создании кастомной модели необходимо сразу настроить её на этапе начала проекта. Изменить стандартную модель
Userв уже существующем проекте очень сложно (придётся переносить данные).Не забудьте протестировать миграции! Если вы используете кастомную модель, неправильно настроенные миграции могут привести к потере данных.
Если вы используете поле
emailкак идентификатор, помните, что оно должно быть уникальным. Убедитесь, что в вашем проекте это корректно настроено.
Практическое применение
- В реальных проектах, таких как социальные сети или интернет-магазины, расширение пользователя позволяет существенно упростить работу с данными профиля.
- На собеседованиях могут попросить объяснить, как работает кастомизация модели пользователя, а также какие ограничения есть у Django.
- Знание этих инструментов позволит адаптировать Django под сложные сценарии, требуемые бизнес-логикой.
Основной подход зависит от ваших задач: если изменения минимальны, используйте One-to-One связь, а для серьёзных изменений — кастомную модель. Теперь у вас есть ключевые инструменты для настройки пользователя в Django!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ