Django にはログイン、ログアウト、パスワード管理を行うことができるの認証系のビューが有ります。
まず初めにどの様な認証系のViewがあるか簡単に解説します。次にカスタマイズする方法を解説します。
カスタマイズ可能な機能はテンプレート、URL、 View、ミドルウェア、フォームなど有りますが、今回はテンプレートをカスタマイズする方法を解説します。
この記事は以下の読者を想定して書いています。
- Djangoの認証系の機能を使いたいがカスタマイズ方法が分からない
- Djangoのチュートリアルをやったが他のチュートリアルも参考にしたい
Django 3.2, Python 3.9のバージョンで確認しています。
コマンドはLinux/MacOS用に書いています。
認証のView一覧
Djangoで用意されている認証系の機能を”権限不要ページ”と”権限必要ページ”で分類してみました。これらを見ると認証系で提供している機能はログイン・ログアウト、とパスワード関連のみです。
- ログアウト
- パスワード変更
- パスワード変更完了
URL
urlpatterns = [
path('accounts/', include('django.contrib.auth.urls')),
]
この様にdjango.contrib.auth.urlsをインクルードすると、以下のURLが利用できます。[name=”]の部分は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’]
各URLで読み込まれるテンプレートは以下の様になっています。
URL名 | 読み込むテンプレート |
login | registration/login.html |
logout | registration/logged_out.html |
password_change | registration/password_change_form.html |
password_change_done | registration/password_change_done.html |
password_reset | registration/password_reset_form.html |
password_reset_done | registration/password_reset_done.html |
password_reset_form | registration/password_reset_confirm.html |
password_reset_complete | registration/password_reset_complete.html |
これとは別にパスワードリセット時に送るメール用のテンプレートと件名をカスタマイズできます。
メールを生成するためのテンプレート名は、registration/password_reset_email.html、件名はregistration/password_reset_subject.txtです。
次の章から上記9つのhtmlファイルと1つのtxtファイルをカスタマイズ方法を解説します。
プロジェクトの作成
以下のコードを実行しmysiteというプロジェクトと、accountsというappを作成します。
django-admin startproject mysite
cd mysite
python manage.py startapp accounts
次に以下の画像の青枠で記した様に、フォルダやファイルを作成します。accountsフォルダ配下にあるprofile.htmlファイルはログイン後にリダイレクトするページとして使います。
※venvというフォルダは仮想環境用に作りましたが、作成する必要はありません。
urls.pyの編集
mysite/urls.pyとaccounts/urls.pyを以下の様に編集します。
mysite/urls.py
http://127.0.0.1:8000/accounts/loginの様にアクセスできるようにするため、mysite/urls.pyは以下の様に編集します。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accounts.urls')),
]
accounts/urls.py
accounts/urls.pyは以下の様に編集します。ログイン後はaccounts/profile/にリダイレクトされるため、そのためのpathを追加します。
profileページはlogin_required関数を使ってログイン必須ページとしています。
from django.urls import path, include
from django.views.generic.base import TemplateView
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('', include('django.contrib.auth.urls')),
path('profile/', login_required(TemplateView.as_view(template_name='accounts/profile.html'))),
]
settings.pyの編集
mysite/settings.pyを編集します。INSTALLED_APPSに作成したaccountsアプリを追加します。
INSTALLED_APPS = [
(中略)
'accounts',
]
LANGUAGE_CODEと、TEMPLATES変数の’DIRS’キーを次の様に変更します。
LANGUAGE_CODE = 'ja'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
以下略
}
]
次にパスワードリセット申請を実行した時に送るメールをコンソールで確認するためにEMAIL_BACKENDを追加します。
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
htmlファイルの編集
以下に紹介するhtmlファイルはdjango/contrib/admin/templates/配下にあるhtmlファイルを参考に作っています。
templates/base.html
templates/base.htmlを以下の様に編集します。このhtmlファイルをベースに他のhtmlファイルを作成します。デザインの要素を省いたシンプルなコードにしています。
認証Viewにはtitle変数が設定されているものが多いので、title変数があった場合は表示する様にしています。
{% load i18n %}
<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content_title %}
{% if title %}<h1>{{ title }}</h1>{% endif %}
{% endblock %}
{% block content %}{% endblock %}
</body>
</html>
login.html
templates/registration/login.htmlログインページを表示するために使用します。
入力エラー、権限がない場合、未ログイン時にアクセスしようとした時のエラーメッセージが表示される様になっています。
url名を使って{% url ‘password_reset’ %}とすることでパスワードリセットへのリンクも配置しています。
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>名前とパスワードが一致しません。正しく入力してください。</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>アクセスしようとしたページを表示する権限がありません。 表示するためには、
アクセス権限のあるアカウントでログインしてください。</p>
{% else %}
<p>このページを見るためにはログインしてください。</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login">
<input type="hidden" name="next" value="{{ next }}">
</form>
<p><a href="{% url 'password_reset' %}">パスワードを忘れましたか?</a></p>
{% endblock %}
このhtmlファイルで名前とパスワードを不正入力した時は以下の様に表示されます。
profile.html
accounts/templates/accounts/profile.htmlはアカウントページを表示するために使います。
このページは、ログインしたユーザ名、パスワード変更へのリンク、ログアウトへのリンクを表示しています。ログインをするとこのページが表示されます。
{% extends "base.html" %}
{% block title %}プロファイル{% endblock %}
{% block content %}
<p>プロファイル</p>
<p>hello {{ request.user.username }}</p>
<a href="{% url 'password_change' %}">パスワード変更</a>
<a href="{% url 'logout' %}">ログアウト</a>
{% endblock %}
logged_out.html
templates/registration/logged_out.htmlはログアウトページを表示するために使います。以下の様に編集します。
{% extends "base.html" %}
{% block content %}
<p>ログアウトしました。</p>
<p><a href="{% url 'login' %}">再ログインする。</a></p>
{% endblock %}
このファイルは以下の様に表示されます。ログアウト用のViewにはtitle=_(‘Logged out’)と設定されています。言語設定に応じて翻訳されるため”ログアウト”と表示されます。
パスワードリセット申請
パスワードリセット申請完了
パスワードリセット