Django 認証Viewのテンプレートをカスタマイズする方法

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名読み込むテンプレート
loginregistration/login.html
logoutregistration/logged_out.html
password_changeregistration/password_change_form.html
password_change_doneregistration/password_change_done.html
password_resetregistration/password_reset_form.html
password_reset_doneregistration/password_reset_done.html
password_reset_formregistration/password_reset_confirm.html
password_reset_completeregistration/password_reset_complete.html
URL, 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’)と設定されています。言語設定に応じて翻訳されるため”ログアウト”と表示されます。

ログアウト時に表示されるページ
ログアウトページ
スポンサーリンク
スポンサーリンク