Курс по Django: https://stepik.org/a/183363
Архив проекта: 69_sitewomen.zip
На этом занятии
мы приступим непосредственно к реализации механизма восстановления паролей, в
соответствии со следующей схемой:
Вначале создадим
шаблон формы password_reset_form.html для ввода E-mail адреса:
{% extends 'base.html' %}
{% block content %}
<h1>Восстановление пароля</h1>
<form method="post">
{% csrf_token %}
{% for f in form %}
<p ><label class="form-label" for="{{ f.id_for_label }}">{{f.label}}: </label>{{ f }}</p>
<div class="form-error">{{ f.errors }}</div>
{% endfor %}
<p ><button type="submit">Сбросить по E-mail</button></p>
</form>
{% endblock %}
И шаблон password_reset_done.html с информацией о
сбросе пароля по E-mail (скопирован из register/password_reset_done.html и немного
изменен):
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<h1>Сброс пароля</h1>
<p >{% translate 'We’ve emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly.' %}</p>
<p >{% translate 'If you don’t receive an email, please make sure you’ve entered the address you registered with, and check your spam folder.' %}</p>
{% endblock %}
Далее,
воспользуемся стандартными классами представлений PasswordResetView и PasswordResetDoneView, у которых
укажем пути к нашим шаблонам. В файле users/urls.py пропишем
следующие строчки:
path('password-reset/',
PasswordResetView.as_view(template_name = "users/password_reset_form.html"),
name='password_reset'),
path('password-reset/done/',
PasswordResetDoneView.as_view(template_name = "users/password_reset_done.html"),
name='password_reset_done'),
Добавим в шаблон
формы авторизации ссылку для восстановления пароля (в файл login.html):
<p ><a href="{% url 'users:password_reset' %}">Забыли пароль?</a></p>
Запустим
веб-сервер, откроем окно авторизации и нажмем на ссылку «Забыли пароль?».
Появляется форма ввода E-mail-адреса
пользователя. Вводим E-mail и нажимаем на
кнопку «Отправить по E-mail». После чего у
нас выскакивает ошибка, что маршрут с именем password_reset_confirm не
определен. Действительно, мы реализовали только первую часть схемы. Давайте
пропишем и вторую.
Сформируем еще
два шаблона:
- файл password_reset_confirm.html:
{% extends 'base.html' %}
{% block content %}
<h1>Новый пароль</h1>
<form method="post">
{% csrf_token %}
<div class="form-error">{{ form.non_field_errors }}</div>
{% for f in form %}
<p ><label class="form-label" for="{{ f.id_for_label }}">{{f.label}}: </label>{{ f }}</p>
<div class="form-error">{{ f.errors }}</div>
{% endfor %}
<p ><button type="submit">Сохранить</button></p>
</form>
{% endblock %}
- файл password_reset_complete.html:
{% extends 'base.html' %}
{% block content %}
<h1>Пароль изменен</h1>
<p >Поздравляем! Вы успешно изменили пароль своего аккаунта. Используйте его для
<a href="{% url 'users:login' %}">входа в систему</a>.</p>
{% endblock %}
И в файле users/urls.py, опять же,
воспользуемся стандартными классами представлений PasswordResetConfirmView и PasswordResetCompleteView:
path('password-reset/<uidb64>/<token>/', PasswordResetConfirmView.as_view(template_name="users/password_reset_confirm.html"), name='password_reset_confirm'),
path('password-reset/complete/', PasswordResetCompleteView.as_view(template_name="users/password_reset_complete.html"), name='password_reset_complete'),
Однако если
сейчас попробовать восстановить пароль, то получим ошибку:
NoReverseMatch
at /users/password-reset/
Она произошла
из-за того, что в стандартном шаблоне registration\password_reset_email.html
используется тег:
{% url 'password_reset_confirm' uidb64=uid token=token %}
без указания
пространства имен users. Поэтому я скопирую этот шаблон и
подправлю в нем этот тег:
{{ protocol }}://{{ domain }}{% url 'users:password_reset_confirm' uidb64=uid token=token %}
И в файле users/urls.py пропишем этот новый
шаблон для класса представления PasswordResetView следующим
образом:
path('password-reset/',
PasswordResetView.as_view(
template_name="users/password_reset_form.html",
email_template_name="users/password_reset_email.html",
success_url=reverse_lazy("users:password_reset_done")
),
name='password_reset'),
Обратите
внимание, что мы здесь же добавили параметр success_url с указанием
пространства имен users. Иначе, при перенаправлении возникла бы
та же ошибка.
Теперь все
проходит, мы видим письмо со ссылкой для восстановления пароля и информационную
страницу о его сбросе на почтовый ящик.
Прежде чем
переходить по этой ссылке, мы сразу пропишем параметр success_url и у класса
представления PasswordResetConfirmView:
path('password-reset/<uidb64>/<token>/',
PasswordResetConfirmView.as_view(
template_name="users/password_reset_confirm.html",
success_url=reverse_lazy("users:password_reset_complete")
),
name='password_reset_confirm'),
(Значение
параметра success_url можно
посмотреть в самом классе PasswordResetConfirmView.)
Снова сделаем
сброс пароля, переходим по ссылке в письме и попадаем на страницу изменения
пароля. Вводим его, и он сохраняется для пользователя с указанным E-mail адресом.
Вот так,
относительно несложно, можно реализовать восстановление паролей во фреймворке Django.
Курс по Django: https://stepik.org/a/183363