Djangoのログイン処理を実装する方法③~パスワードリセット~

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
 

Djangoのログイン処理を実装する方法③~パスワードリセット~” に対して2件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です