Skip to content

Latest commit

 

History

History
385 lines (253 loc) · 11.7 KB

File metadata and controls

385 lines (253 loc) · 11.7 KB

Модуль 9. Урок 56. Авторизация пользователей. Функции authenticate() и login()

В предыдущем уроке мы подключили приложение users, настроили маршруты и убедились, что Django готов работать с системой пользователей. Теперь пришло время реализовать реальный вход пользователя в систему.

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


Как выглядит процесс авторизации в Django

Прежде чем писать код, важно понять общую схему.

Когда пользователь пытается войти в систему, Django выполняет следующую последовательность действий:

  1. Получает логин и пароль из формы.
  2. Проверяет, существует ли такой пользователь.
  3. Сравнивает введённый пароль с хешем в базе данных.
  4. Если всё корректно — создаёт сессию пользователя.
  5. Связывает текущий HTTP-запрос с этим пользователем.

За ключевые шаги отвечают две функции:

  • authenticate()проверяет учетные данные;
  • login()выполняет вход и создаёт сессию.

Создание формы авторизации

Начнём с формы, через которую пользователь будет вводить данные.

Файл users/forms.py

Если файла forms.py ещё нет — создайте его в приложении users.

from django import forms

class LoginUserForm(forms.Form):
    username = forms.CharField(
        label="Логин",
        widget=forms.TextInput(attrs={"class": "form-input"})
    )
    password = forms.CharField(
        label="Пароль",
        widget=forms.PasswordInput(attrs={"class": "form-input"})
    )

Что здесь важно

  • Мы используем обычную форму, не связанную с моделью.
  • Поле password использует PasswordInput, поэтому введённый текст скрыт.
  • Пока мы работаем с username, а не с email — это стандартное поведение Django.

Создание шаблона страницы входа

Теперь создадим HTML-шаблон для отображения формы.

Структура каталогов

Внутри приложения users создайте папки:

users/
└── templates/
    └── users/
        └── login.html

Файл users/templates/users/login.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Вход в Cinemahub</title>
</head>
<body>

<h1>Авторизация в Cinemahub</h1>

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Войти</button>
</form>

</body>
</html>

На данном этапе мы не привязываемся к общему шаблону проекта, чтобы урок оставался универсальным и понятным.


Передача формы в представление

Теперь обновим представление входа, чтобы оно отображало форму.

Файл users/views.py

from django.shortcuts import render
from .forms import LoginUserForm

def login_user(request):
    form = LoginUserForm()
    return render(request, "users/login.html", {"form": form})

Проверка результата в браузере

Запустите сервер:

python manage.py runserver

Перейдите по адресу:

http://127.0.0.1:8000/users/login/

Если вы видите форму с полями логина и пароля — значит:

  • шаблон найден корректно;
  • форма передаётся в контекст;
  • маршрутизация работает правильно.

Проверка учетных данных: функция authenticate()

Теперь добавим логику проверки логина и пароля.

Что делает authenticate()

Функция authenticate():

  • принимает учетные данные;
  • ищет пользователя в базе;
  • проверяет пароль;
  • возвращает объект пользователя или None.

Пример:

from django.contrib.auth import authenticate

user = authenticate(username="admin", password="12345")

Если данные неверны — user будет равен None.


Вход пользователя: функция login()

Если пользователь найден, его нужно «впустить» в систему.

Что делает login()

Функция login(request, user):

  • привязывает пользователя к текущему запросу;
  • сохраняет его ID в сессии;
  • делает пользователя доступным как request.user.

Без вызова login() пользователь не считается авторизованным, даже если пароль верный.


Полная реализация авторизации

Теперь объединим всё в одном представлении.

Обновлённый файл users/views.py

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.urls import reverse
from .forms import LoginUserForm

def login_user(request):
    if request.method == "POST":
        form = LoginUserForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            user = authenticate(
                request,
                username=cd["username"],
                password=cd["password"]
            )
            if user is not None and user.is_active:
                login(request, user)
                return redirect("movies:movie_list")
            else:
                form.add_error(None, "Неверный логин или пароль")
    else:
        form = LoginUserForm()

    return render(request, "users/login.html", {"form": form})

Разбор логики по шагам

  1. Проверяем тип запроса (GET или POST).

  2. Валидируем форму.

  3. Получаем очищенные данные (cleaned_data).

  4. Проверяем пользователя через authenticate().

  5. Если пользователь существует и активен:

    • выполняем вход через login();
    • перенаправляем на список фильмов.
  6. Если данные неверны — добавляем ошибку формы.


Реализация выхода из системы

Для выхода пользователя Django предоставляет функцию logout().

Файл users/views.py

def logout_user(request):
    logout(request)
    return redirect("users:login")

После выхода:

  • сессия очищается;
  • пользователь становится анонимным;
  • request.user.is_authenticated возвращает False.

Проверка авторизации на практике

Шаг 1. Создайте пользователя

Через админ-панель или команду:

python manage.py createsuperuser

Шаг 2. Войдите на страницу авторизации

/users/login/

Введите корректные данные.

Шаг 3. После входа

  • пользователь перенаправляется на страницу со списком фильмов;
  • Django «помнит» пользователя между запросами.

Шаг 4. Отображение пользователя в шаблоне

В Django имя вошедшего пользователя доступно в шаблоне через объект request.user.

В вашем базовом шаблоне можно добавить такой код:

<header>
    <p>Привет, {{ request.user.username }}!</p>
</header>

Типичные ошибки и их причины

Пользователь не входит в систему

Причины:

  • неверный пароль;
  • пользователь не активен (is_active=False);
  • забыли вызвать login().

Ошибка CSRF

Причина — отсутствие {% csrf_token %} в форме.


authenticate() всегда возвращает None

Возможные причины:

  • неверный username;
  • пароль передан не строкой;
  • пользователь не существует.

Практические задания

Задание 1

Добавьте вывод сообщения Вы успешно вошли в систему после успешной авторизации. (В шаблоне эту информацию содержит request.session.login_success)


Задание 2

Измените перенаправление после входа на страницу конкретного фильма.


Задание 3

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


Сравнить решение

Решение задания 1

В представлении:

request.session["login_success"] = True

В шаблоне:

{% if request.session.login_success %}
<p>Вы успешно вошли в систему</p>
{% endif %}

Решение задания 2

return redirect("movies:movie_detail", slug="test-movie")

Решение задания 3

if request.user.is_authenticated:
    return redirect("movies:movie_list")

Вопросы для самопроверки

  1. В чём разница между authenticate() и login()?
  2. Что возвращает authenticate(), если данные неверны?
  3. Почему без login() пользователь не считается авторизованным?
  4. Где хранится информация об авторизованном пользователе?
  5. Что делает logout()?
  6. Почему важен {% csrf_token %}?
  7. Как проверить, авторизован ли пользователь?
  8. Можно ли войти в систему с неактивным пользователем?
  9. Где обычно происходит перенаправление после входа?

Предыдущий урок | Следующий урок