Создаем в Django формы и функционал по восстановлению пароля пользователя


03 июня 2023


Создание страниц для восстановления пароля в Django

На сайтах, где реализуется функционал регистрации пользователя, так же создается и процедура восстановления пароля. Процесс восстановления пароля выполняется из нескольких шагов. Это, например, переход по специальной ссылке, которая высылается в письме. Так как это стандартный функционал для множества сайтов - в Django уже есть простой способ это реализовать. Как это можно сделать и будет рассмотрено на примерах.

 

Как реализуется процесс восстановления пароля

Хоть процесс восстановления пароля - это процедура, через которую все проходили, многие не замечают что она реализуется через несколько страниц:

  1. Страница ввода учетных данных;
  2. Страница, которая подтверждает, что учетные данные найдены и ссылка для восстановления пароля выслана;
  3. Страница, на которую переходят по ссылке из письма для смены пароля. Переход на эту страницу выполняется через уникальный URL;
  4. Страница об успешной смене пароля.

Так как это обычная задача для большинства сайтов в Django уже есть способ сделать это простым способом. В модуле 'django.contrib.auth.urls', кроме возможности login и logout (и других возможностей), так же реализована задача по восстановлению пароля. Процесс по восстановлению пароля, через этот модуль, строится на следующих путях:

  1. accounts/password_reset/ [name='password_reset']
  2. accounts/password_reset/done/ [name='password_reset_done']
  3. accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
  4. accounts/reset/done/ [name='password_reset_complete']

Ссылка отправляется - через раннее настроенный SMTP аккаунт. Для тестирования есть возможность вывода ссылки в лог Django.

Обратите внимание, что хоть в Django, по умолчанию, идентификация пользователя выполняется по его логину (имени пользователя), процедура восстановления пароля требует адрес почты.

Тестовый проект

В примерах ниже используется самый простой проект на Django 4.1. Вы можете создать его следующими командами.

django-admin startproject testproject
cd .\testproject\
python manage.py migrate
python manage.py createsuperuser

 

Создание маршрутов в urls.py

Маршруты, для страниц по восстановлению паролей, можно создать двумя способами.

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

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('django.contrib.auth.urls')),
]

Включение маршрутов 'django.contrib.auth.urls' для сброса пароля в Django

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

from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views


urlpatterns = [
    path('admin/', admin.site.urls),
    path('reset_password/', auth_views.PasswordResetView.as_view(),
         name ='reset_password'),
    path('reset_password_sent/', auth_views.PasswordResetDoneView.as_view(),
         name ='password_reset_done'),
    path('reset/<uidb64>/<token>', auth_views.PasswordResetConfirmView.as_view(),
          name ='password_reset_confirm'),
    path('reset_password_complete/', auth_views.PasswordResetCompleteView.as_view(),
         name ='password_reset_complete'),
]

Включение url из 'django.contrib.auth.urls' для восстановления пароля в Django

В первом варианте, названия путей (параметр name), такие же, что и во втором.

Путь 'reset/<uidb64>/<token>' используется для ссылки, по которой будет переходить пользователь. Через вьюшку 'PasswordResetView' такая ссылка будет сгенерирована и выслана на почту. Ссылка состоит из двух параметров:

  • uidb64 - закодированный base64 идентификатор пользователя;
  • token - хэш сумма из идентификатора пользователя, секрета, временной метки и др.

 

Создание шаблонов

Для каждого из путей должен быть создан шаблон. Общая папка, для хранения всех шаблонов, указывается в файле 'testproject/settings.py'. В примере для статьи указан следующий путь:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        ...
    },
]

Изменение расположения шаблонов в Django

Шаблоны для процесса восстановления пароля, создаются в дополнительной папке 'registration' и имеют следующие имена.

  • password_reset_form.html
  • password_reset_subject.txt - тема письма
  • password_reset_email.html - тело письма
  • password_reset_done.html
  • password_reset_confirm.html
  • password_reset_complete.html

Шаблон запроса на сброс пароля

По пути 'registration/password_reset_form.html' создается шаблон, который используется для создания запроса по восстановлению. Самая простая реализация этого шаблона следующая:

{% block content %}
  <h3>Восстановление пароля</h3>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Отправить</button>
  </form>
{% endblock %}

Шаблон запроса на восстановления пароля в Django

Если email будет найден - пользователь будет переадресован на URL 'reset_password_sent'. Шаблон для этой страницы должен располагаться по пути 'registration/password_reset_done.html'. Пример содержания:

{% block content %}
Инструкция по восстановлению пароля отправлена на указанный email
{% endblock %}

Шаблон подтверждения на восстановление пароля в Django

Шаблон отправляемого письма

Письмо состоит из темы и содержания. Для каждого из них создается отдельный шаблон. В каждом из них могут быть использованы переменные, которые используются в обычных шаблонах. Это, например, переменная 'user' или 'domain', которые могли бы лучше конкретизировать письмо.

Пример темы сообщения, указанный в файле 'registration/password_reset_subject.txt':

Восстановление пароля пользователя {{ user.get_username }} для {{ domain }}

Шаблон темы письма для смены пароля в Django

Заголовок, который будет выводиться при отладке, может начинаться с атрибута '=?utf-8', указывающим на кодировку. Такой формат соответствует RFC 2047. Такая ситуация не касается латиницы.

Пример тела сообщения, указанный в файле 'registration/password_reset_email.html':

{% autoescape off %}
Восстановление пароля для пользователя {{ user.get_username }}. Перейдите по следующей ссылке:
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uid64=uid token=token %}
{% autoescape on %}

Шаблон содержания письма для смены пароля в Django

Шаблон смены пароля

Ссылка в письме ведет на страницу с формой для смены пароля. Этот шаблон должен лежать по пути  'registration/password_reset_confirm.html'. В этом же шаблоне идет проверка на действительность ссылки, по которой был выполнен переход. Это действие выполняется через переменную 'validlink'.

{% block content %}
  {% if validlink %}
    <h1>Смена пароля</h1>
    <form method="post">
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit">Подтвердить</button>
    </form>
  {% else %}
    <p>
      Вероятно ссылка неверна или уже была использована
    </p>
  {% endif %}
{% endblock %}

Шаблон смены пароля для его восстановления в Django

Если смена пароля прошла успешно - будет открыт шаблон 'registration/password_reset_complete.html'.

{% block content %}
<p>Пароль для пользователя успешно сменен</p>
{% endblock %}

Подтверждение смены пароля для его восстановления в Django

Смена языка

Поля некоторых форм отображаются на английском языке. Один из способов это изменить - указать нужный язык проекта в файле 'testproject/settings.py'.

LANGUAGE_CODE = 'ru-RU'

Изменение языка в шаблоне для восстановления пароля в Django

Изменения путей и имени шаблонов

Вы можете изменить путь, по которому можно найти шаблон, заполнив 'template_name' в файле 'urls.py':

from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views


urlpatterns = [
    path('admin/', admin.site.urls),
    path('reset_password/', auth_views.PasswordResetView.as_view(template_name='test.html'),
         name ='reset_password'),
]

 

 

Настройка отправки писем через SMTP

Для отправки писем у вас должны быть указаны настройки пользователя и сервер. Если этого не сделано, но вы уже пытались восстановить пароль, то на моменте отправки письма появится ошибка:

  • [WinError 10061] Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение
  • [WinError 10061] No connection could be made because the target machine actively refused it

Для тестирования отправки писем, без настройки самого аккаунта, можно выполнить ряд настроек, которые устанавливаются в файле 'testproject/settings.py'.

Следующая настройка будет выводить письма в консоли.

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

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

Следующая - сохранять их в папке 'emails' в корне проекта.

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = BASE_DIR / 'emails'

Сохранение писем в файл в Django

Если вы хотите отправлять письма другим пользователям, то вам нужно так же заполнить ряд параметров. Это делается в этом же файле. Вам потребуется указать данные SMTP сервера и пользователя от имени которого будут отправляться письма. Пример полей, которые вам нужно будет указать ниже, но они могут отличаться от используемого сервера.

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'test@gmail.com'
EMAIL_HOST_PASSWORD = '123'

 

...

Теги: #python #django #пользователи #пароль


Каналы
Telegram FixMyPc Telegram Лента FixMyPC RSS Rss
Популярные тэги
О блоге
Этот блог представляет собой конспекты выученного материала, приобретённого опыта и лучшие практики в системном администрировании и программировании.