django-allauthは便利なDjangoの便利な認証モジュールですが、デフォルトでは全くといっていいほどデザインされていません。手順を知っていないとカスタマイズが少々面倒なので備忘も兼ねて残しておきます。
目次
allauthのテンプレート用ディレクトリを作成
まずはallauthのテンプレート用ディレクトリを作成します。
元のファイルをいじることもできなくはないのですが、いじりやすい場所にディレクトリを作ってコピーしてきた方が管理しやすいです。
このサイトのDjango講座ではプロジェクトディレクトリの直下に templates ディレクトリを作成しています。
その中に 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を使う方法については下記の記事をご参照ください。
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© <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ディレクトリにコピーしてきましょう。
socialaccountディレクトリを作成
templates/allauth/ディレクトリの中にsocialaccountディレクトリを、さらにその中にsnippetsディレクトリを作成します。
テンプレートファイルをコピー
作成したディレクトリにテンプレートファイルをコピーします。
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; }
こんな感じです。
とりあえず必要なファイルの場所と、パスを通す方法さえわかっていれば必要なファイルを編集してカスタマイズすることができます。