Продвинутый Django 5 для продолжающих

Прогресс по курсу:  0/193

8.3 Создание кастомной User модели
4 из 5 шагов пройдено
0 из 5 баллов  получено

Django поставляется с предопределенной пользовательской моделью, которая импортируется из django.contrib.auth. Пользовательская модель Django по умолчанию поставляется со следующими полями:

  • username
  • first_name
  • last_name
  • email
  • password
  • groups
  • user_permissions
  • is_staff
  • is_active
  • is_superuser
  • last_login
  • date_joined

Полем идентификации пользователя по умолчанию является имя пользователя. Что делать, если вы хотите использовать поле электронной почты для идентификации пользователей вместо имени пользователя?

Кроме того, в зависимости от потребностей вашего проекта вам могут понадобиться другие поля пользователя, такие как возраст, номер телефона, адрес и т. д.
 

AbstractBaseUser и AbstractUser

Django предоставляет AbstractUser и AbstractBaseUser, которые можно использовать для создания пользовательской модели. Они оба позволяют вам определять свои собственные пользовательские поля. Важно понимать разницу между AbstractUser и AbstractBaseUser в Django, это поможет вам принять правильное решение, какой из них использовать при запуске проекта.
 

AbstractUser

В документации Django говорится, что AbstractUser обеспечивает полную реализацию пользователя по умолчанию в качестве абстрактной модели, что означает, что вы получите полные поля, которые поставляются с моделью пользователя, плюс поля, которые вы определяете.

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


class MyUser(AbstractUser):
    address = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField()

В приведенном выше примере вы получите все поля модели User плюс поля, которые мы здесь определили, а именно address и birth_date.
 

AbstractBaseUser

AbstractBaseUser имеет только функцию аутентификации, у него нет фактических полей, вы предоставите поля для использования при создании подкласса.

Вы также должны указать, какое поле будет представлять имя пользователя, обязательные поля и способы управления этими пользователями.

Чтобы настроить пользователя в Django с помощью AbstractBaseUser, вам необходимо выполнить следующие требования:

  • Создать пользовательскую модель пользователя
  • Определить пользовательский менеджер пользователей
  • Определить пользовательскую модель в settings.py
  • Создание пользовательских форм для создания регистрации пользователя
  • Зарегистрировать пользовательские формы в Django Admin

В этом разделе мы настроим пользовательскую модель с помощью класса AbstractBaseUser

 

Создание пользовательской модели

Предположим, мы хотели создать механизм регистрации пользователей, который принимает одно дополнительных свойство - номер телефона. Также нам нужно использовать адрес электронной почты в качестве логина и наличие username нам совершенно не нужно. Давайте изменим пользовательскую модель с помощью AbstractBaseUser.

Для этого добавим в accounts/models.py следующий код:

from django.core.validators import RegexValidator
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.utils import timezone


class User(AbstractBaseUser):
    email = models.EmailField(max_length=255,unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    created = models.DateTimeField(default=timezone.now)
    phone_regex = RegexValidator(regex=r'^((\+7)|8)\d{10}$',
                                 message="Phone number must be entered in the format: '+79999999999' or '89999999999'.")
    phone_number = models.CharField(validators=[phone_regex], max_length=12, null=True, blank=True)


Для создания поля телефонного номера в модели мы можем использовать специальную библиотеку - https://django-phonenumber-field.readthedocs.io/en/latest/

Но в данном примере я хочу показать вам работу валидаторов полей. Мы импортируем RegexValidator.

Поскольку поле электронной почты является уникальным идентификатором, оно должно быть установлено в unique=True.

  • is_active - вместо удаления пользователей Django позволяет деактивировать пользователей, значение по умолчанию - True.
  • is_staff - это поле указывает, является ли пользователь администратором или нет. Пользователь у которого is_staff=True может войти на сайт администратора Django.


Пользовательская модель также требует некоторых дополнительных свойств, таких как:

  • USERNAME_FIELD - это строка, описывающая уникальный идентификатор; в нашем случае его адрес электронной почты
  • REQUIRED_FIELDS - список обязательных полей, необходимых при создании нового пользователя.

Добавим их в нашу модель:

from django.core.validators import RegexValidator
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.utils import timezone


class User(AbstractBaseUser):
    email = models.EmailField(max_length=255,unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    created = models.DateTimeField(default=timezone.now)
    phone_regex = RegexValidator(regex=r'^((\+7)|8)\d{10}$',
                                 message="Phone number must be entered in the format: '+79999999999' or '89999999999'.")
    phone_number = models.CharField(validators=[phone_regex], max_length=12, null=True, blank=True)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []


Нам также нужно будет добавить разрешения Django в пользовательскую модель. К ним относятся такие методы, как has_perm и has_module_perms.

from django.core.validators import RegexValidator
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.utils import timezone


class User(AbstractBaseUser):
    email = models.EmailField(max_length=255, unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    created = models.DateTimeField(default=timezone.now)
    phone_regex = RegexValidator(regex=r'^((\+7)|8)\d{10}$',
                                 message="Phone number must be entered in the format: '+79999999999' or '89999999999'.")
    phone_number = models.CharField(validators=[phone_regex], max_length=12, null=True, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.is_admin


Эти два метода проверяют, есть ли у пользователя разрешения. Например, суперпользователь может получить доступ к сайту администратора и создать других пользователей. 


  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

Некорректное регулярное выражение для номера телефона. Знак `+` является спецсимволом и его нужно экранировать.

@Sergei_Aleshin, спасибо, исправил.

Ошибка-  is_active - вместо удаления пользователей Django позволяет деактивировать пользователей, значение по умолчанию - False.  По умолчанию True https://docs.djangoproject.com/en/4.2/topics/auth/customizing/#django.contrib.auth.models.CustomUser.is_active

@Sergei_Aleshin, спасибо, исправил.