django-allauthのテンプレートファイルをカスタマイズする方法

django-allauthは便利なDjangoの便利な認証モジュールですが、デフォルトでは全くといっていいほどデザインされていません。手順を知っていないとカスタマイズが少々面倒なので備忘も兼ねて残しておきます。

目次

allauthのテンプレート用ディレクトリを作成

まずはallauthのテンプレート用ディレクトリを作成します。

元のファイルをいじることもできなくはないのですが、いじりやすい場所にディレクトリを作ってコピーしてきた方が管理しやすいです。

このサイトのDjango講座ではプロジェクトディレクトリの直下に templates ディレクトリを作成しています。

その中に allauth/account ディレクトリを作成します。

allauth/account ディレクトリを作成

次にdjango-allauthのデフォルトテンプレートファイルをこのディレクトリにコピーしましょう。

このサイトのDjango講座のようにvenvでPythonの仮想環境を作り、そこにpipでインストールしている場合、C:\Users\ユーザー名\プロジェクト名\venv\Lib\site-packages\allauth\templates ディレクトリに次のフォルダがあるので、カスタマイズしたいものをコピーします。

  • account
  • openid
  • socialaccount

カスタマイズしたいファイルをコピー

settings.pyを編集してパスを通す

settings.pyのTEMPLATESのDIRSに先ほど作成したディレクトリのパスを記述しましょう。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates'),
            os.path.join(BASE_DIR, 'templates', 'allauth')
          ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

テンプレートファイルを編集する

あとはテンプレートファイルを編集するだけです。

例としてサインアップページ、ログインページ、ログアウトページにBootstrapのデザインを適用してみましょう。

DjangoでBootstrapを使う方法については下記の記事をご参照ください。

DjangoでBootstrapを使う方法

base.html

allauth/account 以下にコピーしてきた base.html です。

{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
    <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css' ><!-- bootstrapのCSSを読み込み -->
    {% load bootstrap4 %}<!-- django-bootstrapのテンプレートタグを使用可能に -->
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
    <title>ゆっくり村β</title>
  </head>
  <body class="text-center signin-body">

    <!-- Fixed navbar -->
    <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
    <a class="navbar-brand" href='{% url "moviebbs:index" %}'>ゆっくり村β</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarCollapse">
      <ul class="navbar-nav mr-auto">
        {% if user.is_authenticated %}
            <li class='nav-itme'>
                <span class='navbar-text'>{{ user }} - </span>
            </li>
            <li class='nav-item'>
                <a class="nav-link" href='{% url "account_logout" %}' class='logout nav-link'>ログアウト</a>
            </li>
        {% else %}
            <li class='nav-item'>
                <a class="nav-link" href='{% url "account_login" %}' class='login nav-link'>ログイン</a>
            </li>
            <li class='nav-item'>
                <a class="nav-link" href='{% url "account_signup" %}' class='signup nav-link'>新規登録</a>
            </li>
        {% endif %}
      </ul>
      <form class="form-inline mt-2 mt-md-0" action='{% url "moviebbs:youtube_search" %}' method='get'>
          {% csrf_token %}
          <input class="form-control mr-sm-2" type="text" class='form_control' name="word" placeholder = 'キーワードを入力' value='{{ word }}'>
          <input class="btn btn-outline-primary my-2 my-sm-0" type='submit' class='btn btn-primary' value="YouTubeを検索">
      </form>
    </div>
    </nav>

    {% if messages %}
    <div>
      <strong>Messages:</strong>
      <ul>
        {% for message in messages %}
        <li>{{message}}</li>
        {% endfor %}
      </ul>
    </div>
    {% endif %}

    <div class='container container-maxwidth'>
        {% block content %}
        {% endblock %}
    </div>

    <footer class="footer mt-auto py-3">
      <div class="container container-maxwidth">
        <span class="text-muted">Copyright&copy; <script>document.write(new Date().getFullYear());</script> ゆっくり村β</span>
      </div>
    </footer>

    <!-- Optional JavaScript -->
      <!-- jQuery first, then Popper.js, then Bootstrap JS -->
      <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

  </body>
</html>

7行目でBootstrapのCSSを読み込み、8行目でdjango-bootstrapのテンプレートタグを使用可能にするための記述をしています。

navbarで使用しているログインページやログアウトページへのリンクのURLはallauthのurlをそのまま使用します。

  • サインアップページ:href=”{% url ‘account_signup’ %}”
  • ログインページ:href=”{% url ‘account_login’ %}”
  • ログアウトページ:href=”{% url ‘account_logout’ %}”

ルーティングの記述を確認したり、変更したい場合は allauth本体のaccount/urls.py というファイルに記述されています。

最後の記述はBootstrapで使用しているJavaScriptやJqueryを読み込むためのものです。

signup.html

{% extends "account/base.html" %}

{% block content %}
<h1 class="h3 mb-3 font-weight-normal">新規ユーザー登録</h1>

<form class="form-signin" id="signup_form" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}
  {% bootstrap_form form %}<!-- Bootstrapを適用したフォーム -->
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <button type="submit" class="btn btn-lg btn-primary btn-block" type="submit">新規登録</button>
</form>
{% endblock %}

h1タグやformタグにbootstrapで定義されているクラス名を当ててデザインが適用されるようにしています。

8行目の記述がdjango-bootstrapのテンプレートタグで、このように記述することでbootstrapのデザインが適用されたフォームが出力されます。

login.html

{% extends "account/base.html" %}

{% load i18n %}
{% load account socialaccount %}

{% block content %}

<h1 class="h3 mb-3 font-weight-normal">ログイン</h1>

{% get_providers as socialaccount_providers %}
{% if socialaccount_providers %}

<div class="socialaccount_ballot">
  <ul class="socialaccount_providers">
    {% include "socialaccount/snippets/provider_list.html" with process="login" %}
  </ul>
</div>

{% else %}
<p>{% blocktrans %}If you have not created an account yet, then please
<a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}</p>
{% endif %}

<form class="form-signin" method="POST" action="{% url 'account_login' %}">
  {% csrf_token %}
  {% bootstrap_form form %}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
  <button type="submit" class="btn btn-lg btn-primary btn-block" type="submit">ログイン</button>
</form>

{% endblock %}

同様にlogin.htmlも編集していきます。

3行目の記述はDjangoの多言語機能を利用する設定で、django-allauthのテンプレートでもこの機能が利用されています。このファイルだと例えば20-21行目、30行目でこの機能を利用した記述がされており、Django側の言語設定に合わせて出力する文言を動的に変えてくれています。

この辺りを直接日本語で記述してしまえば3行目の記述も不要になりますが、面倒なのでそのままにしてあります。(ログインページの文言なんて定型文なので)

10行目はソーシャルログイン(OAuth認証)に使うプロバイダが設定されている場合に読み込む設定で、その後のif文でソーシャルプロバイダが設定されている時の分岐処理を行っています。

loout.html

{% extends "account/base.html" %}

{% load i18n %}

{% block content %}

<p>{% trans 'Are you sure you want to sign out?' %}</p>

<form class="form-signin" method="POST" action="{% url 'account_logout' %}">
  {% csrf_token %}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
  {% endif %}
  <button type="submit" class="btn btn-lg btn-primary btn-block" type="submit">{% trans 'Sign Out' %}</button>
</form>

{% endblock %}

必要なのはログアウトするかどうかという確認文とログアウトボタンだけなので特に解説は必要ないですね。

style.css

あとは自作のcssで微調整しましょう。

これは記述が少ないので他のページ用のものと同じ、static/css/style.css に書きました。

/* ログインフォーム周り */
.form-signin {
  width: 100%;
  max-width: 330px;
  padding: 15px;
  margin: auto;
}

.signin-body{
  align-items: center;
  padding-bottom: 40px;
  background-color: #f5f5f5;
}

input#id_remember {
    display: block;
    margin-left: 30px;
}

これで各ページのデザインは次のようになっています。

サインアップページ

サインアップページ

ログインページ

ログインページ

ログアウトページ

ログアウトページ

ソーシャルログインボタンのカスタマイズ

ログインページのソーシャルログインボタンが気に入りませんね。(というかデザインしていない状態ですね)

これを装飾してみましょう。

ソーシャルログインボタンはlogin.htmlの中で別のファイルを呼び出すことで動的に出力されています。

<div class="socialaccount_ballot">
  <ul class="socialaccount_providers">
    {% include "socialaccount/snippets/provider_list.html" with process="login" %}
  </ul>
</div>

3行目の記述ですね。

この場所にソーシャルログインボタンの出力用HTMLが記述されているはずなので、覗いてみましょう。

※このサイトのDjango講座のようにvenvでPythonの仮想環境を作り、そこにpipでインストールしている場合、C:\Users\ユーザー名\プロジェクト名\venv\Lib\site-packages\allauth\templates\socialaccount\snippets

allauth\templates\socialaccount\snippets

こいつですね。こいつを先ほど作成したallauthディレクトリにコピーしてきましょう。

socialaccountディレクトリを作成

templates/allauth/ディレクトリの中にsocialaccountディレクトリを、さらにその中にsnippetsディレクトリを作成します。

socialaccountディレクトリを作成

テンプレートファイルをコピー

作成したディレクトリにテンプレートファイルをコピーします。

authentication_error.htmlとsignup.htmlはsocialaccountディレクトリ直下にコピー、provider_list.htmlはsnippetsディレクトリの中にコピーします。

テンプレートファイルをコピー

それぞれのファイルの担当画面は次のとおりです。

  • authentication_error.html(ソーシャル認証エラー発生時の画面)
  • signup.html(ソーシャル認証サインアップ時の画面)
  • provider_list.html(ソーシャル認証ボタンの一覧表示)

エラー発生時とソーシャル認証サインアップ時のテンプレートの編集は割愛します。

ソーシャルログインボタン用のHTMLを編集

ログイン画面に表示されているソーシャルログインボタンを装飾したいのでprovider_list.htmlを編集していきます。

デフォルトの状態では全てのボタンに同じHTMLタグが付くようになっているので、登録しているソーシャルプロバイダ名ごとに異なるタグを当てるよう編集します。

{% load socialaccount %}

{% get_providers as socialaccount_providers %}

{% for provider in socialaccount_providers %}

{% if provider.name == "Google" %}
<div class="input-group">
  <span class="input-group-addon addon-google">
	<i class="fa fa-fw fa-2x fa-google fa-fw"></i>
  </span>
  <a class="btn btn-lg btn-block btn-google socialaccount_provider {{provider.id}}" href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"> Googleでサインイン</a>
</div>
{% elif provider.name == "Twitter" %}
<div class="input-group">
  <span class="input-group-addon addon-twitter">
	<i class="fa fa-fw fa-2x fa-twitter fa-fw"></i>
  </span>
  <a class="btn btn-lg btn-block btn-twitter  socialaccount_provider {{provider.id}}" href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"> Twitterでサインイン</a>
</div>
{% endif %}

{% endfor %}

ソーシャルログインボタン用のCSSを編集

自作のcssで調整しましょう。

これも他のページ用のものと同じ、static/css/style.css に記述しています。

/* ソーシャルログイン */
.socialaccount_providers {
    padding: 0;
    max-width: 330px;
    margin: auto;
}
.input-group {
	margin: 10px 0px;
}
.addon-google {
	background-color: hsl(345, 83%, 36%);
	border: none;
	border-radius: 2px 0px 0px 2px;
	color: #fff;
}
.btn-google,
.btn-google:hover {
	background-color: hsl(345, 94%, 42%);
	color: #fff;
	border-radius: 0px 2px 2px 0px;
	font-size: 15px;
}
.addon-twitter {
	background-color: #00c6e9;
	border: none;
	border-radius: 2px 0px 0px 2px;
	color: #fff;
}
.btn-twitter,
.btn-twitter:hover {
	background-color: #00d7fa;
	color: #fff;
	border-radius: 0px;
	font-size: 15px;
}

デザインされたソーシャルボタン

こんな感じです。

とりあえず必要なファイルの場所と、パスを通す方法さえわかっていれば必要なファイルを編集してカスタマイズすることができます。

このエントリーをはてなブックマークに追加

コメントを残す

頂いたコメントは一読した後表示させて頂いております。
反映まで数日かかる場合もございますがご了承下さい。