Djangoでパスワード変更画面を実装してみます。
Python + Djangoで独自のユーザ認証を実装するの続きです。
top画面にパスワード変更機能を追加します。DJangoのパスワード変更画面を利用します。
###1.accountsアプリケーション
パスワード変更機能をaccountsに追加することにしました。
(1)accounts\urls.py
パスワード変更用にurlsを追加します
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'), #追加
]
indexはviewをクラスベースにしたので変更しています
(2)accounts\views.py
from django.shortcuts import render
from django.contrib.auth.views import PasswordChangeView, PasswordChangeDoneView
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'
Point
LoginRequiredMixinで、認証を必須としています
パスワード変更、パスワード変更完了は、Djnagoに用意されているビューを利用しています。
form_nameという変数を追加しています
(3)html
password_change.html
パスワード変更画面です。
{% extends "commons/base.html" %}
{% block title %}パスワード変更{% endblock %}
{% block styles %}
{% endblock %}
{% block headertitle %}パスワード変更{% endblock %}
{% block content %}
<div class="row justify-content-md-center">
<div class="col-6">
<form action="" method="POST">
{{ form.non_field_errors }}
{% for field in form %}
<div class="form-group">
<label class="col-6" for="{{ field.id_for_label }}">{{ field.label_tag }}</label>
{{ field }}
{{ field.errors }}
</div>
{% endfor %}
{% csrf_token %}
<div class="form-group row">
<div class="col-sm">
<button type="submit" class="btn btn-primary btn-block">送信</button>
</div>
<div class="col-sm">
<button type="submit" class="btn btn-primary btn-block" onClick="javascript:history.go(-1);">戻る</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
password_change_done.html
パスワード変更のお知らせ画面です。
{% extends "commons/base.html" %}
{% block title %}パスワード変更完了{% endblock %}
{% block styles %}
{% endblock %}
{% block headertitle %}パスワード変更完了{% endblock %}
{% block content %}
<div class="row justify-content-md-center">
<div class="col-4">
<p>パスワードを変更しました。</p>
<div class="form-group row">
<div class="col-6">
<a class="btn btn-primary btn-block" href="{% url 'accounts:index' %}">トップへ</a>
</div>
</div>
</div>
</div>
{% endblock %}
base.html
views.pyで追加したform_nameによって、「パスワード変更」ボタンを自身の画面に表示しないようにしています
{% load staticfiles %}
{% load bootstrap4 %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<title>
{% block title %}{% endblock %}
</title>
<style>
body {
padding : 10px;
}
div.container {
min-width:600px;
}
nav ul#menu {
margin:0px;
padding:0px;
}
nav ul#menu li {
float:right;
list-style-type:none;
text-decoration: underline;
padding-left: 10px;
}
div.header {
padding: 10px;
}
div.header * {
color: white !important;
}
div.header .title {
font-size: 1.2em;
}
{% block styles %}{% endblock %}
</style>
</head>
<body>
<div class="container">
<div class="inner">
<div class="text-right">{{ form_name }}</div>
<div class="row header mysystem-header">
<div class="col-sm title">
{% block headertitle %}{% endblock %}
</div>
<div class="col-sm">
<nav class="pull-right">
<ul id="menu">
{% if user.is_authenticated %}
<li><a href="{% url 'logout' %}" class="logout">ログアウト</a></li>
{% if form_name == "password_change" %}
{% else %}
<li><a href="{% url 'accounts:password_change' %}" class="logout">パスワードの変更</a></li>
{% endif %}
{% else %}
{% endif %}
</ul>
</nav>
</div>
</div>
<br/>
<div class="content">
{% block content %}{% endblock %}
</div>
</div>
</div>
<script src="{% static "js/jquery-3.3.1.min.js" %}"></script>
<script src="{% static "js/bootstrap.bundle.min.js" %}"></script>
{% block scripts %}{% endblock %}
</body>
</html>
###2.動作確認
サーバを起動
(venv) C:\data\python\work\myproject>manage.py runserver
サイトにアクセス
Djangoを使うと、認証情報のmodel、更新処理などを全部やってくれるのでとても楽に開発できそうです