【django】ログイン認証機能:パスワード変更機能を組み込む方法
2021.04.08 /
本記事では、PythonのWebフレームワークdjangoを使って、ログイン認証機能におけるアカウントのパスワード変更機能を組み込む方法を解説していきます。
djangoには最初から使える様々な機能が備わっています。
もちろんログイン認証で使用する基本的な機能も備わっています。
初めから備わっている機能のうち、ここではアカウントパスワード変更機能をWebアプリケーションに組み込む方法を見ていきましょう。
Djangoに組み込まれているパスワード変更機能
Djangoには初めから様々な便利な機能が用意されています。
その中の一つ、アカウント認証に使われるパスワードの変更機能について解説していきます。
django.contrib.auth
django.contrib.authにより、djangoのアカウント認証で必要になる機能が提供されます。
django.contrib.authはフォルダの階層構造を示しており、仮想環境venvを使用している場合は、次のパスを示しています。
venv\Lib\site-packages\django\contrib\auth\
実際にdjango.contrib.authのフォルダ内を確認してみてください。
urls.pyやviews.pyなどたくさんのpyファイルが保存されていることがわかります。
これらフォルダ内のファイル(スクリプト)をプログラムの先頭でimportすることで、パスワード変更機能などが使えるようになるということです。
django.contrib.auth.views
django.contrib.auth内のviews.pyにアカウント認証で使われる様々な機能が記載されています。
今回のパスワード変更には、その中の以下2つのビュークラスを使用します。
- PasswordChangeView
- PasswordChangeDoneView
PasswordChangeView
クラスPasswordChangeViewはアカウントのパスワードを変更する処理を提供します。
class PasswordChangeView(PasswordContextMixin, FormView):
form_class = PasswordChangeForm
success_url = reverse_lazy('password_change_done')
template_name = 'registration/password_change_form.html'
title = _('Password change')
パスワードの変更が成功したら、urls.pyでnameがpassword_change_doneにページ遷移することがわかります。
PasswordChangeDoneView
クラスPasswordChangeDoneViewはアカウントのパスワード変更が成功した場合の処理を提供します。
class PasswordChangeDoneView(PasswordContextMixin, TemplateView):
template_name = 'registration/password_change_done.html'
title = _('Password change successful')
django.contrib.auth.urls
django.contrib.auth内のurls.pyには、アカウント認証で使用できるURLパターンが用意されています。
accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']
このように便利なurls.pyが用意されているのですが、本記事のパスワード変更機能では使用しません。
パスワード変更機能を追加してみよう
では実際にWebアプリケーションにパスワード変更機能を追加してみましょう。
以下記事で作成したWebアプリケーションに対してパスワード機能を追加します。
【django】ログイン認証機能を組み込む方法(ログイン・ログアウト)
次の流れでWebアプリケーションにパスワード変更機能を追加していきます。
- urls.pyにパスワード変更クラスへのルーティングを追加
- パスワード変更及び完了を表示するテンプレートの作成
- base.htmlにパスワード変更ページへのリンクを貼る
最終的に完成するWebアプリケーションの画面遷移を以下に記します。
- ログイン後のトップページ
- アカウント名をクリックして、プルダウンメニューを表示
- パスワード変更画面
- パスワード変更完了通知画面
このWebアプリケーションを作成していきましょう。
urls.pyにルーティングを追加
まずはプロジェクトのurls.pyにdjango.contrib.auth.viewsの2つのクラス(PasswordChangeView、PasswordChangeDoneView)へのルーティングを追加します。
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views # 追加
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('five.urls')),
path('accounts/', include('django.contrib.auth.urls')),
path('accounts/password_change_form/', auth_views.PasswordChangeView.as_view(template_name='registration/password_change.html'), name='password_change_form'), # 追加
path('accounts/password_change_done/', auth_views.PasswordChangeDoneView.as_view(template_name='registration/password_change_finish.html'), name='password_change_done'), # 追加
]
上記urls.pyでは、django.contrib.authからviewsをインポート(auth_viewsとする)して、2つのクラスへのルーティングを追加しています。
各ルーティングではオプションtemplate_nameを使って、クラスで使用するテンプレートを指定しています。
すでに備わっているクラスを使用しているので、views.pyへの記入は一切必要ありません。
テンプレートの追加
urls.pyの記入ができたら、次にパスワード変更と完了を表示するテンプレートを作成します。
アプリケーションフォルダ内のtempletes\registration内にpassword_change.htmlとpassword_change_finish.htmlを次のように作成しましょう。
password_change.html
{% extends "five/base.html" %}
{% block content %}
<h2>Password Change</h2>
<form method="post" style="padding-left:20px;">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Change Password</button>
</form>
{% endblock %}
password_change_finish.html
{% extends "five/base.html" %}
{% block content %}
<h2>Password Change Done</h2>
{% endblock %}
これでパスワード変更機能の実装はほとんど完了となります。
ソースコード
上記で示したページ以外のページは、次に示すように変更します。
base.html
{% load static %}
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE-edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0">
<title>OFFICE54</title>
<link rel="stylesheet" href="{% static 'five/common.css' %}">
<script src="https://kit.fontawesome.com/d86c726e71.js" crossorigin="anonymous"></script>
</head>
<body>
<header>
<div>
<p>OFFICE</p>
</div>
<div>
{% if user.is_authenticated %}
<ul class="header-munu-ul">
<li class="nav_item"><a href="#" class="menu-name js-dropdown"><i class="far fa-user-circle" style="margin-left:-10px;margin-right:10px"></i><small>{{ user.username }}</small></a>
<div class="panel js-dropdown-menu">
<ul class="panel-inner">
<li class="panel_item"><a href="{% url 'logout' %}">Logout</a></li>
<li class="panel_item"><a href="{% url 'password_change_form'%}">Change Password</a></li>
</ul>
</div>
</li>
</ul>
{% else %}
<p><a href="{% url 'login' %}">ログイン</a></p>
{% endif %}
</div>
</header>
<div id="wrapper">
<nav id="nav-left">
<div id="nav">
<ul id="nav-ul">
<li class="nav-li"><a href="{% url 'index' %}" class="nav-li-a"><i class="fa fa-tachometer" style="margin-right:15px"></i>Dashboard</a></li>
<li class="nav-li"><a href="#" class="nav-li-a"><i class="fas fa-list" style="margin-right:15px"></i>App1</a></li>
{% if user.is_authenticated %}
<li class="nav-li"><a href="{% url 'password_change_form'%}" class="nav-li-a"><i class="fas fa-server" style="margin-right:15px"></i>User Password Change</a></li>
{% endif %}
</ul>
</div>
</nav>
<main id="main">
{% block content %}
{% endblock %}
</main>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
var $dropdown = $('.js-dropdown');
var DURATION = 200; //アニメーションの速さ
function fadeOutMenu(){
$dropdown.removeClass('is-active')
.next('.js-dropdown-menu')
.stop()
.slideUp(DURATION);
}
$('.js-dropdown').on('click', function(){
var $self = $(this);
if(!$self.hasClass('is-active')){
fadeOutMenu();
}
$self.toggleClass('is-active')
.next('.js-dropdown-menu')
.stop().slideToggle(DURATION);
})
$(document).on('click touchend', function(event) {
if (!$(event.target).closest('.js-dropdown').length) {
fadeOutMenu();
}
});
});
</script>
</body>
</html>
common.css
common.cssに追加したコードを以下に記します。
a{
text-decoration: none;
}
header .header-munu-ul{
display: flex;
height: 50px;
list-style: none;
}
header li{
align-items: center;
justify-content: center;
}
header .menu-name{
color: #898a8e;
/*color: #0099FF;*/
display: flex;
align-items: center;
justify-content: center;
height: 50px;
font-size: 20px;
font-weight: 600;
}
header .nav_item{
position: relative;
}
header .nav_item:hover{
background-color: rgb(230,230,230);
}
header .panel{
position: absolute;
top:52px;
left: 0;
right: 0;
margin: auto;
overflow: hidden;
width: 100%;
display: none;
background-color: white;
z-index: 100;
border-radius: 3px;
box-shadow: 0 0px 20px rgba(0,0,0,0.2);
}
header .panel_item{
display: block;
margin: 20px 10px;
font-size: 14px;
}
header .panel_item a{
color: #0099FF;
font-weight: 100;
}
header .panel_item a:hover{
text-decoration: underline;
}
header .nav_item{
display: block;
width: 230px;
text-align: center;
}
.is-active{
color: orange !important;
}
まとめ
みなさんパスワード変更機能はきちんと追加することはできましたか。
本記事では、Djangoで最初から備わっている機能を利用することで、非常に簡単にパスワード変更機能を組み込むことができました。
ぜひそういった機能を利用して、Webアプリケーションの開発時間を短縮していきましょう。