テンプレートのカスタマイズする前に知っておきたいこと

横瀬明仁氏:カスタマイズで苦労するポイント2です。「テンプレートを修正するのにコツがいる」という困りごとです。まずは仕組みを理解しておきましょう。テンプレートをカスタマイズする前に知っておきたいこととして、テンプレートの優先順位、テンプレートの継承、Django管理サイト本体のテンプレート構成という3つを挙げます。1つずつ説明していきます。

テンプレートの優先順位

まずは1番目。Djangoがテンプレートのパスから実ファイルを探しにいくことを、テンプレートのルックアップと呼びます。そのルックアップの際には、探し出すディレクトリの優先順位があります。

Django管理サイトの本体のテンプレートは、プロジェクト側からは直接触れないので、テンプレートのルックアップの優先順位の仕組みを使います。そのDjango管理サイトの参照先のテンプレートを差し替えたり、Django管理サイトの本体のテンプレートを継承して、一部分を書き換えたりすることが可能になります。

(スライドを指して)その優先順位1がこれです。設定ファイルのTEMPLATESのDIRSで指定したディレクトリです。2つ目に優先されるのが、INSTALLDED_APPSに登録されたインストール済みアプリケーションのうち、django.contrib.adminよりも上に追加しているアプリケーション配下のtemplatesディレクトリです。Django管理サイト本体のテンプレート用ディレクトリが、最後に適用されます。

細かいことはさておき、設定ファイルのTEMPLATESのDIRSで指定したディレクトリが最優先で検索されることだけ把握しておけばOKです。

テンプレートの継承

2番目に、テンプレートの継承について説明します。これはDjangoの仕組みなので、Django管理サイトだけに特化した話ではありません。あるテンプレートでextendsタグを使って、親テンプレートを継承します。その親テンプレートに書かれている特定のブロックだけを書き換える仕組みがあります。例えば、親テンプレートにwelcome-msgというブロックがあり、それだけを書き換えることができます。これがテンプレートの継承です。

Django管理サイト本体のテンプレート構成

Django管理サイト本体のテンプレート構成を知っておかなければならない。これが3番目です。Django管理サイトの本体にどんなテンプレートがあるのか。あるいは、どの画面で使われているのかについては、ぜひ押さえておきたいところです。

Django管理サイトの本体のテンプレートは、Djangoのインストールディレクトリ配下のcontrib/admin/templatesに配置されています。実際に見てみると、Django管理サイトの本体がズラッと並んでいます。Django 3.2では、ナビゲーションサイドバーで使われる2つのテンプレートが追加されて、全部で47ファイルあります。全部覚えておく必要はありません。

押さえておくべきは、それぞれの画面でどのテンプレートがメインとして使われているかで、それについては把握しておいたほうがよいと思います。

例えば、ログイン画面ならadminのlogin.html、ホーム画面ならadminのindex.htmlといったように、メインのテンプレートが1つずつあります。まずはそれを把握しておきます。

モデル一覧画面では、change_list.htmlがメインで使われています。でも実際には、ほかのテンプレートも数多く使われています。base.htmlとbase_site.htmlは必ず、どのテンプレートからも継承されています。

そのほかにもextendsタグだけではなくincludeタグなど、テンプレートタグによってさまざまなテンプレートが使われています。これはカスタマイズの状況によって増減します。

実際にどのテンプレートが使われているかについては、django-debug-toolbarというライブラリがあるので、そのTemplatesパネルを利用すれば簡単に確認できます。

テンプレートのカスタマイズ方針

(スライドを指して)ここまで説明したテンプレートの優先順位やテンプレートの継承、Django管理サイト本体のテンプレート構成を把握した上で、具体的にどのようにテンプレートをカスタマイズすればよいかを図式化したのがこの図です。

Django管理サイトの本体のテンプレートは直接書き換えられないので、テンプレートのルックアップの仕組みを利用して、最も優先度の高いTEMPLATESのDIRSで指定したディレクトリに、Django管理サイト本体のテンプレートと同じパス、同じ名前で配置します。

そしてテンプレートの継承の仕組みを使って、Django管理サイト本体の一部のみを書き換えることができます。あるいは、ちょうどよいブロックタグが見つからなければ、つまり継承がうまく使えなければ、Django管理サイト本体のものと同名のパス、同名のファイル名で配置することでこちらが優先されるので、丸々置き換えることもできます。

(スライドを指して)これはテンプレートをカスタマイズするための、実際のコード例です。設定ファイルでは、TEMPLATESのDIRSにBASE_DIR直下のtemplatesを指定しています。

そして、優先順位が最も高くなるディレクトリにadminのbase.htmlを新規作成して配置したあと、extendsタグで継承して、一部のブロックのみを書き換えています。そうすることで、ヘッダーの「ようこそ○○」という表示が、「○○としてログイン中」のようにカスタマイズできました。これが実際の例です。

それでは2つ目のまとめです。「テンプレートを修正するのにコツがいる」という問題に対しては、テンプレートの優先順位とテンプレートの継承の仕組みを使ってカスタマイズすることで解決できます。これを知っていれば、Django管理サイトのカスタマイズの幅がぐんと広がります。

CSSのカスタマイズ前に知っておきたいこと

3つ目の困りごと、「画面のスタイルを変えるのが大変」について説明したいと思います。これもまずは、先ほどのテンプレートと同じように、仕組みから理解していきましょう。

まず知っておきたいことは、静的ファイルの優先順位。そしてテンプレートを継承して、CSSファイルを追加するための仕組み。さらに、ModelAdminでCSSファイルを追加するための仕組みについてです。

静的ファイルの優先順位

まず1つ目。Djangoで静的ファイルを配置する場所は、テンプレートと同じように複数の候補があって、それらにも優先順位が規定されています。

まず、優先順位1位は、設定ファイルのSTATICFILES_DIRSで指定したディレクトリです。ひな型プロジェクトの設定ファイルには書かれていないので、自分で追加する必要があります。

優先順位2位は、先ほどと同じように、INSTALLED_APPSに登録されたアプリケーションのうち、adminよりも上に書かれたアプリケーションのstatic配下のディレクトリです。優先順位3位が、本体の静的ファイル用のディレクトリです。

こちらについても、STATICFILES_DIRSで指定したディレクトリが最優先ということだけ把握しておけば、OKです。

テンプレートを継承してCSSファイルを追加する仕組み

2つ目。テンプレートを継承して、CSSファイルを追加するための仕組みを理解するためには、Django管理サイト本体のbase.htmlのheadタグの内容を見ておく必要があります。

(スライドを示し)このように書かれているのが、headタグの中身です。CSSに関する部分を抜粋した部分ですが、まずbase.cssが読み込まれます。これはDjango管理サイト全体の基本スタイルが定義されています。

2番目が、extrastyleブロックです。これはbase.htmlを継承した各画面のメインコンテンツのテンプレートからオーバーライドして、追加のCSSファイルを読み込むために用意されたブロックです。例えばadmin/login.htmlでは、admin/css/login.cssが読み込まれるように、extrastyleブロックがオーバーライドされています。

3番目に、似たようなものでextraheadというものがあります。extraheadブロックはモデルごとの画面からオーバーライドされていて、JavaScriptや静的ファイルも含んで読み込むようにしたブロックです。あとは、レスポンシブ用のスタイルシートも読み込まれています。新しいCSSを読み込む時には、このextrastyleブロックを継承して、書き換えて追加するのがよいと思っています。

(スライドを指して)図式したものがこれです。テンプレートを継承して、extrastyleブロックを書き換えて、CSSファイルを追加する方法です。まずテンプレートの継承を使ってbase.htmlを継承して、extrastyleブロックをオーバーライドして、新たなCSSを読み込むようにします。このCSSの置き場所は、設定ファイルのSTATICFILES_DIRSディレクトリに置くのがよいでしょう。

このextrastyleブロックを継承した時は、まずbase.cssよりも、先ほど見たようにあとで読み込まれるので、カスケードで上書きすることもできるし、新たなスタイルも定義できます。

実際のカスタマイズ例です。テンプレートのadmin/base.htmlでは、親テンプレートのextrastyleブロックを書き換えています。先ほど説明したように、設定ファイルはSTATICFILES_DIRSをBASE_DIRの配下のstaticということにしています。

(スライドを指して)ここで指定したbase_extra.cssには、ヘッダの背景をオレンジ色にしたいという変更を加えています。そうすると、画面が変わりました。これはbase.htmlをカスタマイズしたので、すべての画面のスタイルに影響するようなカスタマイズになります。

ModelAdminでCSSファイルを追加するための仕組み

3番目はModelAdminでCSSファイルを追加するための仕組みです。これはシンプルです。

ModelAdminのMedia.cssで指定したCSSファイルは、モデル一覧画面、追加画面、変更画面、削除確認画面という4つのテンプレートのextrahead。先ほど説明した3つ目のextraheadブロックで読み込まれるような仕組みになっています。こういう仕組みが提供されていることを把握しておく必要があります。ただし、読み込まれるのがこの4テンプレートだけということには注意が必要です。

(スライドを指して)実際のコードがこちらです。shopアプリケーションのadmin.pyのBookAdminというMediaのクラスを指定して、その中にcssという属性を作ります。このように書いておくことで、新しいCSSが自動的に読み込まれるようになります。そのCSSは、STATICFILES_DIRSの下に置いておきます。

例えば、タイトルという列の背景色だけを黄色にするなど、そういったカスタマイズができるようになります。

画面スタイルの変更は2つの方法で対応できる

ここまでが、カスタマイズで苦労するポイント3の「画面のスタイルを変えるのが大変」ということに対する解決策でした。ここでは、スタイルを変えるための方法を大きく2つ説明しました。

テンプレートでextrastyleブロックをオーバーライドして、新しいCSSファイルを読み込む方法。または、ModelAdminのMedia.cssを使って、新しいCSSファイルを読み込む方法です。

ということで、ポイント1番目で、AdminSiteやModelAdminを使って簡単にカスタマイズする方法。ポイント2番目で、テンプレートのカスタマイズをする方法。ポイントの3番目で、CSSのカスタマイズについて説明してきました。

ここまで説明したやり方で、Django管理サイトのたいていのカスタマイズについては、もう実現できるはずです。まずはポイント1から3までで説明した3点を理解するようにしておいてください。

(次回に続く)