Djangoのログイン認証のパスワードリセット処理を実装する方法をご紹介します。
以下の記事の続きです。
Djangoのログイン処理を実装する方法②~パスワード変更~
目次
条件
- Django 2.1.3
- Python 3.7.0
- PyCharm Professional
パスワードリセット処理
パスの追加
パスワードリセット処理を使用するためにurls.pyにパスを追加します。
from django.contrib import admin from django.urls import path, include from django.views.generic.base import TemplateView from django.contrib.auth import views as auth_views urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('django.contrib.auth.urls')), path('', TemplateView.as_view(template_name='home.html'), name='home'), path('password_change/', auth_views.PasswordChangeView.as_view(template_name='password_change_form.html'), name='password_change'), path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'), path('password_reset/', auth_views.PasswordResetView.as_view(template_name='password_reset_form.html'), name='password_reset'), # 追加 path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'), name='password_reset_done'), # 追加 path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'), name='password_reset_confirm'), # 追加 path('reset/done/', auth_views.PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'), name='password_reset_complete'), # 追加 ]
テンプレート追加
以下のパスからパスワード変更用のテンプレートをコピーします。
コピー元
- \venv\Lib\site-packages\django\contrib\admin\templates\registration\password_reset_form.html
- \venv\Lib\site-packages\django\contrib\admin\templates\registration\password_reset_done.html
- \venv\Lib\site-packages\django\contrib\admin\templates\registration\password_reset_confirm.html
- \venv\Lib\site-packages\django\contrib\admin\templates\registration\password_reset_complete.html
コピー先(templatesフォルダの下)
- \templates\password_reset_form.html
- \templates\password_reset_done.html
- \templates\password_reset_confirm.html
- \templates\password_reset_complete.html
動作確認
manage.py runserverを実行して以下のURLを開きます。
http://127.0.0.1:8000/password_reset/
http://127.0.0.1:8000/password_reset/done/
http://127.0.0.1:8000/reset/done/
以下のような表示になればOKです。
パスワードリセット画面の変更
このままでは管理画面を継承しているため、継承元を変更します。
以下4つのファイルについて「extends」を変更します。
- password_reset_form.html
- password_reset_done.html
- password_reset_confirm.html
- password_reset_complete.html
変更前
{% extends "admin/base_site.html" %}
変更後
{% extends 'base.html' %}
再度動作確認をすると以下のような画面になります。
(画面デザインは適宜変更してください。)
リンクの追加
base.htmlにパスワードリセットのリンクを追加します。
未ログイン状態のみ表示されるようにします。
<!-- templates/base.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{% block title %}Django Auth Tutorial{% endblock %}</title> </head> <body> <main> {% if user.is_authenticated %} <li><a href="{% url 'logout' %}" class="logout">ログアウト</a></li> {% if form_name == "password_change" %} {% else %} <li><a href="{% url 'password_change' %}" class="logout">パスワード変更</a></li> {% endif %} {% else %} <li><a href="{% url 'login' %}" class="login">ログイン</a></li> <li><a href="{% url 'password_reset' %}">パスワードリセット</a></li> {% endif %} {% block content %} {% endblock %} </main> </body> </html>
メール送信設定
パスワードリセット時のメール送信処理について設定します。
コンソール出力
開発環境でメールを送信する必要がない場合、メール情報をコンソール出力して確認する方法があります。
settings.pyに「EMAIL_BACKEND」を以下のように設定します。
# sample/settings.py # メール情報のコンソール出力 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
パスワードリセット画面からメール送信を行うと、コンソールに以下のようなメール文が出力されます。
MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: =?utf-8?b?MTI3LjAuMC4xOjgwMDAg44Gu44OR44K544Ov44O844OJ44Oq44K744OD44OI?= From: webmaster@localhost To: sample@mail.sample.co.jp Date: Wed, 14 Nov 2018 01:55:05 -0000 Message-ID: <154216050569.15624.209423990845700430@DESKTOP-2R7EC85> このメールは 127.0.0.1:8000 で、あなたのアカウントのパスワードリセットが要求されたため、送信されました。 次のページで新しいパスワードを選んでください: http://127.0.0.1:8000/reset/MQ/51a-77efc24ce9f5571cfde0/ あなたのユーザー名 (念のため): admin ご利用ありがとうございました! 127.0.0.1:8000 チーム ------------------------------------------------------------------------------- [14/Nov/2018 10:55:05] "GET /password_reset/done/ HTTP/1.1" 200 771
メール本文にあるリンクをクリックすると、新しいパスワードを入力する画面が表示されます。
新しいパスワードを入力してパスワードの変更ボタンを押すと、パスワードが変更され以下の画面が表示されます。
ファイル出力
開発環境でメールを送信する必要がない場合、コンソール出力の他にファイル出力して確認する方法もあります。
settings.pyに「EMAIL_BACKEND」を以下のように設定します。
# メール情報のファイル出力 EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" EMAIL_FILE_PATH = os.path.join(BASE_DIR, "sent_emails")
パスワードリセット処理を行うと、プロジェクトフォルダの下に「sent_emails」というフォルダが作成され、メール本文がlogとしてファイル出力されます。
メール送信
メール送信する場合、以下のように設定します。
# sample/settings.py EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.test.com' EMAIL_PORT = 587 EMAIL_HOST_USER = 'test@test.com' EMAIL_HOST_PASSWORD = 'passwordpassword' EMAIL_USE_TLS = True # TLS (Transport Layer Security)設定 DEFAULT_FROM_EMAIL = 'test@test.com' # メールのfrom
メールのfromはデフォルトで「webmaster@localhost」という設定になっています。
(django/conf/global_settings.pyの「DEFAULT_FROM_EMAIL」に記述されている)
smtpの設定によっては「@localhost」という値が含まれるとメールが送信されない場合があるので、settings.pyで改めて「DEFAULT_FROM_EMAIL」を設定しなおす方が無難です。
以上でパスワードリセット処理の追加は終わりです。
参考
本記事は主に以下のサイトを参考にさせていただきました。
Django Password Reset Tutorial (Part 3)
https://wsvincent.com/django-user-authentication-tutorial-password-reset/
Django