django-allauth : テンプレートのカスタマイズ
django-allauthを使ってみた結果ユーザのログインページが味気ない感じだった。
ここを修正していこうと思う。
https://qiita.com/s-katsumata/items/b667c81a127223d2e868
こちらにテンプレートのカスタマイズ方法があった。これを参考にテンプレートをカスタマイズしてみようと思う。
django-allauthのテンプレートのコピー
コマンドを使ってファイルを操作することに苦手なのでここもメモしておく。
まずコピーのコマンドは以下のような形式である。
#windowsの場合 copy コピー元ファイル コピー先のディレクトリ #mac,linuxの場合 cp コピー元ファイル コピー先ディレクトリ
つぎにコピー元のファイルがどこに有るか?
django-allauthはpip でインストールした。pip でインストールした場合には、pip show モジュール名で情報参照できるようだ。
pip show django-allauth
Name: django-allauth Version: 0.38.0 Summary: Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication. Home-page: http://github.com/pennersr/django-allauth Author: Raymond Penners Author-email: raymond.penners@intenct.nl License: UNKNOWN Location: /anaconda3/envs/django36/lib/python3.6/site-packages Requires: python3-openid, requests-oauthlib, requests, Django Required-by:
locationがdjango-allauthのモジュールだ。ここからaccount,openid,socialaccount,base.htmlをディレクトリごとにコピーしておく。コピー先はテンプレートの優先順位を上げたい思惑からBASE_DIR/config/templates/allauth以下にコピーする。するとallauth以下にaccount,openid,socialaccountディレクトリが置かれる状態となる。
テンプレートはドキュメントで以下のように言及されている。
allauth ships many templates, viewable in the allauth/templates directory.
https://django-allauth.readthedocs.io/en/latest/templates.html#overridable-templates
#参考 #mac, linuxの場合 cp -r /Users/chiaki/opt/anaconda3/lib/python3.7/site-packages/allauth/templates コピー先ディレクトリ #-rオプションはディレクトリごとコピーすることができる
settings.pyのテンプレートの読み込み先を追加する
settings.pyのDIRSの欄にallauth部分を追加する。
djangoのテンプレートの読み込みは優先順序がある。それはtemplateのDIRSをまず読み込み、該当するテンプレートがなかった場合に各アプリのtemplatesディレクトリ(つまりAPP_DIRS)以下を読み込みに行く。そして言うまでもないが、各アプリはsettings.pyのINSTALLED_APPSに登録されて使われることが前提である。allauthの場合も同様、INSTALLED_APPSにallauthを登録するして初めてつかわれる。このことはテンプレートにおいてはallauthアプリ以下にあるテンプレートを読み込んでいるに過ぎない。したがってDIRSにカスタマイズしたallauthテンプレートのパスを記せば、カスタマイズのテンプレートを純正のテンプレートを無視して自己カスタマイズしたテンプレートを読みこむことになる。
https://docs.djangoproject.com/ja/2.2/topics/templates/#support-for-template-engines
具体的なコード例
config/settings.py にて TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, "config", "templates"), os.path.join(BASE_DIR, "config", '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', ], }, }, ] # 上記の追加はBASE_DIR/config/templates/allauthのテンプレ読込先を追加したことを意味する!
上記の追加がなければ、BASE_DIR/config/templates以下のテンプレートをまず探して、該当テンプレートがなければAPP_DIRSを探す。そしてallauth純正のテンプレートを探し当てる。上記を追加すればBASE_DIR/config/templates以下のテンプレートをまず探す。なければ、BASE_DIR/config/templates/allauth以下にテンプレートがないか探す。ここにカスタマイズしたテンプレートを置けば純正allauthテンプレートを探す前に見つけてもらえるのでカスタマイズテンプレートが実際使われる。
テンプレートのカスタマイズ
各テンプレートはextends base.htmlとされているので、それに対しbootstrapのコードを加える。
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> <h1>Hello, world!</h1> <!-- 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>
forms.pyのカスタマイズ
forms.pyのフィールドにclassのアトリビュートを足してbootstrap効果をつけたいと考える。この場合はどうするか。。。?
https://django-allauth.readthedocs.io/en/latest/forms.html#forms
https://www.reddit.com/r/django/comments/3uykx8/customizing_djangoall_auth/
結論から言うと、settings.pyにカスタムしたフォームを使う宣言と、allauthのloginformを継承した子フォームさえ作成すれば良い。
settings.pyにカスタムしたフォームを使う宣言
ACCOUNT_FORMS = {'login': 'myapp.forms.CustomLoginForm'}
上記のように宣言すると、settings.pyにてallauth純正ではなく自分がカスタムしたフォームを使う挙動に変更される。したがってmyapp/forms.pyにてLoginFormを継承したクラスを作成すればよい。
https://django-allauth.readthedocs.io/en/latest/forms.html#account-forms
デフォルトでは以下のような設定になっているカスタムする場合は下記を参考にkeyをsettings.pyに書き込む。。
ACCOUNT_FORMS = { 'login': 'allauth.account.forms.LoginForm', 'signup': 'allauth.account.forms.SignupForm', 'add_email': 'allauth.account.forms.AddEmailForm', 'change_password': 'allauth.account.forms.ChangePasswordForm', 'set_password': 'allauth.account.forms.SetPasswordForm', 'reset_password': 'allauth.account.forms.ResetPasswordForm', 'reset_password_from_key': 'allauth.account.forms.ResetPasswordKeyForm', 'disconnect': `allauth.socialaccount.forms.DisconnectForm`, }
allauthのloginformを継承した子フォームの作成
from allauth.account.forms import LoginForm class CustomLoginForm(LoginForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for field in self.fields.values(): field.widget.attrs['class'] = "form-control"