Программы
Пользователи и авторизация (логин) в Django, кастомизация пользователя

Пользователи и авторизация (логин) в Django, кастомизация пользователя

В Django есть множество встроенных возможностей, которые позволяют не реализовывать многие классы для стандартных операций. Среди них - авторизация. Django изначально предоставляет пользовательскую систему. Но её можно использовать лучше, чем по умолчанию.

В предыдущей заметке об админ-панели Django мы уже познакомились с пользователями и авторизацией Django. Но это было довольно поверхностно и только в рамках админ-панели. Если же мы хотим добавить что-то своё в пользователей и авторизацию пользователей на сайте, нам нужно расширить уже имеющуюся систему необходимыми возможностями.

Изображение Python 3.11. Что нового?

Заменяем стандартную Django модель для пользователей на свою

Для того, чтобы начать разработку своего кастомного пользователя, создадим приложение, которое будет за него отмечать -

$ python3 ./manage.py startapp user

После чего в нём создадим модель, которая будет отвечать за хранение и предоставление информации о пользователе - ./user/models.py:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.validators import validate_slug
from django.utils.translation import ugettext_lazy as _


class User(AbstractUser):
    username = models.CharField(
        verbose_name="Никнейм",
        max_length=150,
        unique=True,
        validators=[validate_slug],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )

    email = models.EmailField(verbose_name='E-mail', blank=True, unique=True, null=True)
    email_checked = models.DateTimeField(blank=True, null=True)

    def __str__(self):
        return '%s (%s)' % (self.get_full_name(), self.email)

Наследуемся от стандартного AbstractUser, добавляем необходимую валидацию, сообщения об ошибке и тд. Если нам не нужен email (а так тоже часто бывает) - делаем необязательными стандартные поля, ответственные за email.

Не забываем добавить в админку, как это делалось в этой заметке. А также зарегистрировать в конфигурационном файле ./application/settings.py:

INSTALLED_APPS = [
    ...
    'user.apps.UserConfig',
    ...
]


AUTH_USER_MODEL = 'user.User'

Первое - подгрузка самого приложения, второе - указываем, какая модель будет моделью в Django, отвечающей за пользователя. К слову, после этого регистрация нашего супер-юзера слетит (ибо уже другая модель). Придётся снова делать createsuperuser.

Добавляем логин на сайт Django

Чтобы наша моделька и в целом вся пользовательская система работала на всём сайте, а не только в админке, нам нужно сделать пару дополнительных правок. Модель у нас уже есть, но, как минимум, надо добавить url для приложения. Например, application/urls.py:

from django.urls import path, include

urlpatterns = [
    ...
    path('user/', include('user.urls', namespace='user')),
    ...
]

И в самом приложении - user/urls.py:

from django.urls import path
from .views import UserLoginView

app_name = 'user'

urlpatterns = [
    path(r'login/', UserLoginView.as_view(), name='login'),
]

Можете заметить, что здесь мы используем view для логина пользователя в Django. Давайте его определим, используя уже встроенный в django.contrib.auth:

from django.contrib.auth.views import LoginView

from .froms import LoginForm


class UserLoginView(LoginView):
    form_class = LoginForm
    template_name = 'user/login.html'

То есть достаточно указать шаблон для отображения и форму, которая будет принимать и валидировать данные с фронтенда. В частности, форму логина можно сделать с помощью стандартной в файле user/forms.py:

from django.contrib.auth.forms import AuthenticationForm


class LoginForm(AuthenticationForm):
    pass

По умолчанию используется username и password - достаточно хорошо для нас. Ну и сам шаблон формы user/templates/user/login.html:

{% extends  'layout/default.html' %}

{% block content %}
<div class="box">
    <h4 class="form-header">Вход в систему</h4>

    <form method="post">
        {% csrf_token %}
        <input type="hidden" name="next" value="{{ next }}">

        {{ form }}

        <button type="submit" class="btn btn-primary btn-block">Войти</button>
    </form>
</div>
{% endblock %}

После логина вы будете перенаправлены по адресу, указанному в application/settings.py:

LOGIN_URL = '/user/login/'
LOGIN_REDIRECT_URL = '/'

Первый url для тех, кто хочет авторизоваться, второй - для тех, кто только что вошёл.

Теперь мы можем авторизоваться с нашим пользователем, которого мы создали командой python ./manage.py createsuperuser, как регистрировать, а также как этим пользоваться - в будущей заметке.