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

Курс по Django: https://stepik.org/a/183363

Смотреть материал на YouTube | RuTube

Архив проекта: 60_sitewomen.zip

На прошлом занятии мы подготовили приложение и функции представления для реализации авторизации пользователя. И чтобы все было понятнее, вначале пропишем логику полностью вручную. Начнем с создания формы отображения ввода логина и пароля. Для этого создадим файл forms.py в приложении users и объявим в нем класс LoginUserForm следующим образом:

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'}))

То есть, мы описали форму не связанную с моделью с двумя полями для ввода логина и пароля.

Следующим шагом сформируем шаблон для отображения этой формы. Так же, как и в приложении women, создадим подкаталог templates, а в нем подкаталог users. И уже здесь разместим файл login.html со следующим содержимым:

{% extends 'base.html' %}
 
{% block content %}
<h1>Авторизация</h1>
 
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <p ><button type="submit">Войти</button></p>
</form>
 
{% endblock %}

Затем в файле users/views.py функцию login_user() перепишем в следующем виде:

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

После запуска веб-сервера на странице:

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

увидим отображение формы для входа. Однако нет отображения главного меню. Но мы это пока оставим и сосредоточимся на функции авторизации.

Реализация авторизации пользователя

Так как форма отправляет данные по POST-запросу, то в функции login_user() вначале сделаем проверку на этот тип запроса, а затем, следующую логику обработки принятых данных:

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 and user.is_active:
                login(request, user)
                return HttpResponseRedirect(reverse('home'))
    else:
        form = LoginUserForm()
    return render(request, 'users/login.html', {'form': form})

Мы здесь вначале создаем форму LoginUserForm с набором принятых данных request.POST. Затем, проверяем форму на корректность (валидность) и если проверка проходит, то создаем временную переменную cd, которая ссылается на очищенные принятые данные формы. На основе полей username и password мы пытаемся с помощью функции authenticate() аутентифицировать пользователя по таблице user БД. Если пользователь с указанной парой логин/пароль находится в БД и является активным (не забанен, например), то вызывается ключевая функция login(), которая создает запись в сессии, авторизуя текущего пользователя на сайте. После этого делается перенаправление на главную страницу. В случае каких-либо ошибок снова форма отображается в браузере пользователя, предлагая ему еще раз попробовать ввести логин и пароль.

Давайте посмотрим, как это все будет работать. На данный момент у нас с вами имеется только один пользователь (он же суперпользователь). Вводим неверные данные и видим, что форма отобразилась снова, так как пользователь не был найден в БД. Если же ввести верные логин/пароль, то произойдет перенаправление на главную страницу.

Видим, что функционал в базовом варианте работает. Но нам пока не показываются никакие сообщения о возможных ошибках. Сейчас на данном этапе мы оставим все как есть, а сейчас реализуем функционал по выходу пользователя (logout).

Перейдем в функцию logout_user() и вызовем в ней стандартную функцию logout() фреймворка Django с перенаправлением на форму авторизации:

def logout_user(request):
    logout(request)
    return HttpResponseRedirect(reverse('login'))

Давайте ее протестируем. Перейдем по адресу:

127.0.0.1:8000/users/logout/

и мы оказались не на той странице, так как имя login связано с маршрутом приложения women. Нам здесь нужно дополнительно прописать пространство имен users следующим образом:

return HttpResponseRedirect(reverse('users:login'))

Теперь все работает как задумывалось.

Проверим, действительно ли пользователь вышел из системы. Откроем страницу админ-панели:

http://127.0.0.1:8000/admin/

и мы автоматически были перенаправлены на страницу авторизации. Значит, выход действительно был выполнен. Функция представления logout_user() работает.

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

Курс по Django: https://stepik.org/a/183363

Видео по теме