Djangoのパスワードリセット機能を試します。
以下のリンクの続きです。
Python + Djangoで独自のユーザ認証を実装する
Python + Djangoでパスワード変更画面を実装する
###1.パスワードリセットのフロー
パスワードリセットは、システム上で、メールアドレスを入力して送信し、ユーザはメール受信後に、本文に記載されているURLをクリックします。パスワード変更画面(パスワードリセット用)が開くので、パスワードを変更すると、パスワードリセット完了の画面が表示され完了します。
- (1)パスワードリセット(メールアドレス入力)画面
- (2)パスワードリセット(メール送信)画面
- (3)メールのURLをクリック
- (4)パスワードリセット(パスワード変更)画面
- (5)パスワードリセット(パスワードリセット完了)画面
Djangoでは、このパスワードリセットも最初から実装されているのでそれを利用します。
###2.実装
####(1)accounts\urls.py
パスワードリセット用に、URLを4つ追加します。
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('', views.index.as_view(), name='index'),
path('password_change/', views.PasswordChange.as_view(), name='password_change'),
path('password_change/done/', views.PasswordChangeDone.as_view(), name='password_change_done'),
path('password_reset/', views.PasswordReset.as_view(), name='password_reset'), #追加
path('password_reset/done/', views.PasswordResetDone.as_view(), name='password_reset_done'), #追加
path('reset/<uidb64>/<token>/', views.PasswordResetConfirm.as_view(), name='password_reset_confirm'), #追加
path('reset/done/', views.PasswordResetComplete.as_view(), name='password_reset_complete'), #追加
]
####(2)accounts\views.py
パスワードリセット用に、views.pyを編集します。formクラスはDjangoで用意されているのでそのまま利用します。
from django.shortcuts import render
# PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteViewを追加
from django.contrib.auth.views import PasswordChangeView, PasswordChangeDoneView, PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import generic
from django.urls import reverse_lazy
class index(LoginRequiredMixin, generic.TemplateView):
"""メニュービュー"""
template_name = 'accounts/top.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # 継承元のメソッドCALL
context["form_name"] = "top"
return context
class PasswordChange(LoginRequiredMixin, PasswordChangeView):
"""パスワード変更ビュー"""
success_url = reverse_lazy('accounts:password_change_done')
template_name = 'accounts/password_change.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # 継承元のメソッドCALL
context["form_name"] = "password_change"
return context
class PasswordChangeDone(LoginRequiredMixin,PasswordChangeDoneView):
"""パスワード変更しました"""
template_name = 'accounts/password_change_done.html'
# --- ここから追加
class PasswordReset(PasswordResetView):
"""パスワード変更用URLの送付ページ"""
subject_template_name = 'accounts/mail_template/reset/subject.txt'
email_template_name = 'accounts/mail_template/reset/message.txt'
template_name = 'accounts/password_reset_form.html'
success_url = reverse_lazy('accounts:password_reset_done')
class PasswordResetDone(PasswordResetDoneView):
"""パスワード変更用URLを送りましたページ"""
template_name = 'accounts/password_reset_done.html'
class PasswordResetConfirm(PasswordResetConfirmView):
"""新パスワード入力ページ"""
success_url = reverse_lazy('accounts:password_reset_complete')
template_name = 'accounts/password_reset_confirm.html'
class PasswordResetComplete(PasswordResetCompleteView):
"""新パスワード設定しましたページ"""
template_name = 'accounts/password_reset_complete.html'
# --- ここまで
####(3)templates\accounts\password_reset_form.html
{% extends "commons/base.html" %}
{% block headertitle %}
パスワードリセット
{% endblock %}
{% block content %}
<form action="" method="POST">
{{ form.non_field_errors }}
<p>メールを受信してパスワードの変更手続きを行います。</p>
<p>メールアドレスを入力して送信ボタンを押してください。</p>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label_tag }}</label>
{{ field }}
{{ field.errors }}
</div>
{% endfor %}
{% csrf_token %}
<pre>メールアドレスはあらかじめシステムに登録が必要です。
メールが届かない場合はシステム管理者に連絡してください。</pre>
<br/>
<div class="form-group row">
<div class="col-6">
<button type="submit" class="btn btn-primary btn-block">送信</button>
</div>
</div>
</form>
{% endblock %}
####(4)templates\accounts\password_reset_done.html
{% extends "commons/base.html" %}
{% block headertitle %}
パスワードリセット(メール送信)
{% endblock %}
{% block content %}
<form action="" method="POST">
<p>パスワードリセットのメールを送信しました。
<br/>
メールに記載されているリンクからパスワードの再設定を行ってください。
<br/>
<br/>
<br/>
<a class="btn btn-primary col-4" href="{% url 'accounts:index' %}">ログイン画面へ</a>
</p>
</form>
{% endblock %}
####(5)templates\accounts\password_reset_confirm.html
{% extends "commons/base.html" %}
{% block content %}
<form action="" method="POST">
{{ form.non_field_errors }}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label_tag }}</label>
{{ field }}
{{ field.errors }}
</div>
{% endfor %}
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-block">送信</button>
</form>
{% endblock %}
####(6)templates\accounts\password_reset_complete.html
{% extends "commons/base.html" %}
{% block content %}
<form action="" method="POST">
<p>
パスワード再設定を完了しました。<br>
<a class="btn btn-primary btn-block" href="{% url 'accounts:index' %}">ログイン</a>
</p>
</form>
{% endblock %}
以上で実装終わりです。
※パスワードリセット(メールアドレス入力)画面で入力するメールアドレスは、プロジェクトの認証ユーザに設定されているメールアドレスである必要があります。管理サイトからメールアドレスを設定しましょう。
###3.動作確認
では、確認してみます。
####(3)メール
送信されたメール。ユーザ:Djangoに設定したメールアドレスに送信されています。
django 様
下記URLよりサイトにアクセスし、パスワードの再設定を行ってください。
再設定用URL
http://localhost:8000/reset/MQ/4yb-77d2a24a746ddeceb805/
####(5)パスワードリセット(パスワードリセット完了)画面
パスワードリセットもDjangoは簡単です。