テンプレートLink to this heading
Django はウェブフレームワークなので、HTML を動的に生成する便利な手段が必要でした。最も一般的なアプローチは、テンプレートに頼ることです。テンプレートには、出力したい HTML を書いた静的な部分と、動的なコンテンツを挿入する方法を書いた特別な構文の部分からなります。テンプレートを使って HTML ページを作るハンズオンの例については、チュートリアル 3 を見てください。
Django プロジェクトは、1つまたは複数のテンプレートエンジンで構成できます (テンプレートを使わなければ、ゼロでも構いません)。Django は、Django テンプレート言語 (DTL) と呼ばれる独自のテンプレートシステムや、人気のある代替テンプレートである Jinja2 用のバックエンドをビルトインで同梱しています。他のテンプレート言語用のバックエンドはサードパーティから入手できるかもしれません。 カスタムテンプレートバックエンド を参照してください。
Django は、バックエンドにかかわらず使用できる、テンプレートの読み込みとレンダリングのための標準の API を定義しています。読み込みのパートでは、指定された名前からテンプレートを探し、テンプレートを前処理し、通常はメモリ上のデータに変換します。レンダリングのパートでは、テンプレートの中にコンテキストデータを埋め込み、最終的な文字列を返します。
Django テンプレート言語 (DTL) はDjango 用のテンプレートシステムです。Django 1.8 までは、ビルトインのオプションしか選択できませんでした。小さな癖もありますが、とても良いテンプレートライブラリです。他のバックエンドを無理して選択しなければならない特別な理由がない限り、DTL を使用することをおすすめします。アプリケーションを書いてテンプレートを配布しようと考えている場合は、特にそうです。たとえば、Django のテンプレートを含んでいる django.contrib.admin のような contrib アプリは、DTL を使用しています。
歴史的な理由により、テンプレートエンジンの一般的なサポートと Django テンプレート言語の実装は、両方とも django.template 名前空間に定義されています。
Django テンプレート言語Link to this heading
構文Link to this heading
Django テンプレートは、 Django テンプレート言語を使ってマークアップされたテキスト文書や Python 文字列です。いくつかの構文はテンプレートエンジンによって認識され、解釈されます。主なものは変数とタグです。
テンプレートは、コンテキストともにレンダリングされます。レンダリングでは、変数が見つかると、コンテキスト内に記録された変数の値に置換され、タグが実行されます。それ以外の文字列は、そのまま出力されます。
Django テンプレート言語の構文は、4つの構成要素に分類できます。
変数Link to this heading
変数は、コンテキストから値を出力します。コンテキストは、キーと値をマッピングする辞書のようなオブジェクトです。
変数はこのように {{ と }} で囲まれます:
My first name is {{ first_name }}. My last name is {{ last_name }}.
コンテキストが {'first_name': 'John', 'last_name': 'Doe'} の場合、このテンプレートは次のようにレンダリングされます:
My first name is John. My last name is Doe.
辞書ルックアップ、属性ルックアップ、リストインデックスルックアップはドット記法で実装されています:
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
変数が呼び出し可能オブジェクトに解決される場合、テンプレート・システムは引数なしで呼び出し、呼び出し可能オブジェクトの代わりにその結果を使用します。
フィルタLink to this heading
フィルタは変数やタグの引数の値を変換します。
たとえばこのようなものです:
{{ django|title }}
コンテキストを {'django': 'the web framework for perfectionists with deadlines'} とすると、このテンプレートは次のようにレンダリングされます:
The Web Framework For Perfectionists With Deadlines
引数を必要とするフィルタもあります:
{{ my_date|date:"Y-m-d" }}
関連項目: 組み込みフィルタのリファレンス 、 独自のテンプレートフィルタの書き方
コンポーネントLink to this heading
エンジンLink to this heading
django.template.Engine は Django テンプレートシステムのインスタンスをカプセル化します。 Engine を直接インスタンス化する主な理由は、 Django プロジェクトの外で Django テンプレート言語を使うためです。
django.template.backends.django.DjangoTemplates は、 django.template.Engine を Django のテンプレートバックエンド API に適応させる薄いラッパーです。
テンプレートLink to this heading
django.template.Template はコンパイルされたテンプレートを表します。テンプレートは Engine.get_template() または Engine.from_string() で取得できます。
同様に django.template.backends.django.Template は django.template.Template を一般的なテンプレート API に適応させるための薄いラッパーです。
コンテキストLink to this heading
django.template.Context はコンテキストデータの他にいくつかのメタデータを保持します。これはテンプレートをレンダリングするために Template.render() に渡されます。
django.template.RequestContext は Context のサブクラスで、現在の HttpRequest を保存し、テンプレートコンテキストプロセッサを実行します。
共通 API には等価な概念がありません。コンテキストデータはプレーンな dict で渡され、現在の HttpRequest は必要に応じて別途渡されます。
ローダーLink to this heading
テンプレートローダーが責任を持つのは、テンプレートの検索、テンプレートの読み込み、Template オブジェクトを返すことです。
Django はいくつかの ビルトインのテンプレートローダー を提供していて、 カスタム テンプレートローダー をサポートしています。
コンテキストプロセッサLink to this heading
コンテキストプロセッサは、現在の HttpRequest を引数としておけとり、データの dict をレンダリングコンテキストに追加して返します。
主な用途は、すべてのビューでコードを繰り返すことなく、すべてのテンプレートで共有される共通のデータをコンテキストに追加することです。
Django は多くの 組み込みのコンテキストプロセッサ を提供し、独自のコンテキストプロセッサを追加実装することもできます。
テンプレートエンジンのサポートLink to this heading
設定Link to this heading
テンプレートエンジンは、TEMPLATES で設定できます。ここには、各エンジンに対する設定のリストを設定します。デフォルト値は空リストです。startproject コマンドで生成された settings.py には、以下のように便利な値がいくつか設定されます。
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
# ... some options here ...
},
},
]
BACKEND は、Django テンプレートバックエンド API を実装したテンプレートエンジンのクラスへの、ドット区切りの Python path です。ビルトインのバックエンドは、django.template.backends.django.DjangoTemplates と django.template.backends.jinja2.Jinja2 です。
ほとんどのエンジンはファイルからテンプレートを読み込むため、各エンジンのトップレベルの設定には次の2つの設定があります。
DIRSには、エンジンがテンプレートのソースファイルを検索するディレクトリのリストを、検索順に定義します。APP_DIRSには、エンジンがインストールしたアプリケーション内のテンプレートを検索するべきかどうかを指定します。各バックエンドは、アプリケーション内でテンプレートを保存するべきサブディレクトリ名として、慣習的な名前を定義しています。
めったにないことですが、同じバックエンドの複数のインスタンスを、オプションだけ変えて設定することも可能です。その場合、各エンジンに対して、NAME にユニークな名前を設定しなければなりません。
OPTIONS には、バックエンド特有の設定を書きます。
使い方Link to this heading
django.template.loader モジュールは、テンプレートを読み込むための2つの関数を定義しています。
- get_template(template_name, using=None)Link to this definition
この関数は、指定した名前のテンプレートを読み込み、
Templateオブジェクトを返します。戻り値の正確な型はテンプレートを読み込んだバックエンドに依存します。それぞれのバックエンドは独自の
Templateクラスを持っています。get_template()は各テンプレートエンジンを見つけるまで順番に試します。テンプレートが見つからない場合、TemplateDoesNotExistを発生します。テンプレートが見つかったが無効な構文を含んでいる場合、TemplateSyntaxErrorを発生します。テンプレートがどのように検索され読み込まれるかは、各エンジンのバックエンドと設定によって異なります。
検索を特定のテンプレートエンジンに限定したい場合は、
using引数にそのエンジンのNAMEを渡します。Partial loading:
When using the
DjangoTemplatesbackend, a specific fragment from a template can be loaded by name. This fragment should have been previously defined using thepartialdeftemplate tag:from django.template.loader import get_template # Load an entire template. template = get_template("template.html") # Load a specific fragment from a template. partial = get_template("template.html#partial_name")When loading a partial, the returned object behaves like a regular
Templatebut contains only the partial's content.See Template partials for more information about defining and using template fragments.
- select_template(template_name_list, using=None)Link to this definition
select_template()はget_template()に似ていますが、1つのテンプレート名の代わりにテンプレート名のリストを取ります。各名前のテンプレートを順番に探し、最初に見つかったテンプレートを返します。
テンプレートの読み込みに失敗した場合、 django.template で定義されている以下の2つの例外が発生する可能性があります:
- exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)Link to this definition
この例外はテンプレートが見つからない場合に発生します。デバッグページの template postmortem に入力するために、以下のオプション引数を受け付けます:
backend例外が発生したテンプレートバックエンドのインスタンス。
triedテンプレートを見つける際に試されたソースのリスト。フォーマットは
(origin, status)を含むタプルのリストです。ここでoriginは origin-like オブジェクトで、statusはテンプレートが見つからなかった理由を表す文字列です。chainテンプレートを読み込もうとしたときに発生した例外
TemplateDoesNotExistの中間値のリストです。これはget_template()のような、与えられたテンプレートを複数のエンジンから読み込もうとする関数で使用されます。
- exception TemplateSyntaxError(msg)Link to this definition
この例外は、テンプレートが見つかったが、エラーを含んでいる場合に発生します。
get_template() と select_template() が返す Template オブジェクトは以下のシグネチャを持つ render() メソッドを提供しなければなりません:
- Template.render(context=None, request=None)Link to this definition
与えられたコンテキストを用いて、このテンプレートをレンダリングします。
contextを指定する場合は、dictでなければなりません。もし指定しなければ、エンジンは空のコンテキストでレンダリングします。requestを指定する場合は、HttpRequestでなければなりません。テンプレートエンジンは、テンプレート内では、このインスタンスと CSRF トークンを使用できるようにする必要があります。そのための実装はバックエンドに依存します。
以下に、検索アルゴリズムの例を示します。この例の場合、TEMPLATES 設定は次のようになっています。
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"/home/html/example.com",
"/home/html/default",
],
},
{
"BACKEND": "django.template.backends.jinja2.Jinja2",
"DIRS": [
"/home/html/jinja2",
],
},
]
get_template('story_detail.html') を呼び出した場合、Django は次の順番にファイルを探します。
/home/html/example.com/story_detail.html('django'エンジン)/home/html/default/story_detail.html('django'エンジン)/home/html/jinja2/story_detail.html('jinja2'エンジン)
select_template(['story_253_detail.html', 'story_detail.html']) を呼び出した場合、Djangoは以下の順番にファイルを探します。
/home/html/example.com/story_253_detail.html('django'エンジン)/home/html/default/story_253_detail.html('django'エンジン)/home/html/jinja2/story_253_detail.html('jinja2'エンジン)/home/html/example.com/story_detail.html('django'エンジン)/home/html/default/story_detail.html('django'エンジン)/home/html/jinja2/story_detail.html('jinja2'エンジン)
Django がテンプレートを発見したら、その時点で探索は停止します。
テンプレートを含む各ディレクトリの中のサブディレクトリにテンプレートを整理することは可能であり、望ましいことです。慣習としては、Django アプリごとにサブディレクトリを作り、必要に応じてその中にサブディレクトリを作ります。
正気を保つためにも、そうしてください。すべてのテンプレートを1つのディレクトリのルートレベルに保存すると、面倒なことになります。
サブディレクトリ内のテンプレートを読み込むには、次のようにスラッシュを使います:
get_template("news/story_detail.html")
上記と同じ TEMPLATES オプションを使用すると、以下のテンプレートを読み込もうとします:
/home/html/example.com/news/story_detail.html('django'エンジン)/home/html/default/news/story_detail.html('django'エンジン)/home/html/jinja2/news/story_detail.html('jinja2'エンジン)
さらに、テンプレートの読み込みやレンダリングの繰り返しを減らすために、Django は処理を自動化するショートカット関数を提供しています。
- render_to_string(template_name, context=None, request=None, using=None)Link to this definition
render_to_string()はget_template()のようにテンプレートを読み込んで、すぐにrender()メソッドを呼び出します。以下の引数を取ります。template_name読み込んでレンダリングするテンプレートの名前です。テンプレート名のリストの場合、 Django はテンプレートを見つけるのに
get_template()の代わりにselect_template()を使います。contextレンダリングのためにテンプレートのコンテキストとして使用される
dictです。requestオプション
HttpRequestで、テンプレートのレンダリング処理中に利用できます。usingオプションのテンプレートエンジン
NAMEです。テンプレートの検索はそのエンジンに制限されます。
使用例:
from django.template.loader import render_to_string rendered = render_to_string("my_template.html", {"foo": "bar"})
See also the render() shortcut which calls
render_to_string() and feeds the result into an
HttpResponse suitable for returning from a view.
最後に、設定されたエンジンを直接使用することもできます:
- enginesLink to this definition
テンプレートエンジンは
django.template.enginesで利用できます:from django.template import engines django_engine = engines["django"] template = django_engine.from_string("Hello {{ name }}!")ルックアップのキー (この例では
'django') はエンジンのNAMEです。
組み込みのバックエンドLink to this heading
- class DjangoTemplatesLink to this definition
Django テンプレートエンジンを設定するには、 BACKEND を 'django.template.backends.django.DjangoTemplates' にセットします。
APP_DIRS が True の場合、 DjangoTemplates エンジンはインストールされたアプリケーションの templates サブディレクトリにあるテンプレートを探します。この一般名は後方互換性のために残されています。
DjangoTemplates エンジンは以下の OPTIONS を受け付けます:
'autoescape': HTMLのオートエスケープを有効にするかどうかをコントロールする真偽値です。デフォルトは
Trueです。'context_processors': リクエストでテンプレートがレンダリングされるときにコンテキストを生成するために使用される呼び出し可能オブジェクトへの Python のドット区切りパスのリストです。これらの呼び出し可能オブジェクトはリクエストオブジェクトを引数として取り、コンテキストにマージされるアイテムのdictを返します。デフォルトは空のリストです。
詳しくは
RequestContextを参照してください。'debug': テンプレートのデバッグモードのオン/オフを切り替える真偽値です。もしTrueなら、テンプレートのレンダリング中に例外が発生した場合、fancy エラーページに詳細なレポートが表示されます。このレポートには、該当する行がハイライトされたテンプレートのスニペットが含まれます。デフォルトは
DEBUG設定の値です。'loaders': テンプレートローダクラスへの Python のドット区切りパスのリストです。各Loaderクラスは特定のソースからテンプレートをインポートする方法を知っています。任意で、文字列の代わりにタプルを使うこともできます。タプルの最初の項目はLoaderクラス名で、それ以降の項目は初期化時にLoaderに渡されます。デフォルトは
DIRSとAPP_DIRSの値に依存します。詳しくは ローダーの種類 を参照してください。
'string_if_invalid': 無効な(例えばスペルミスのある)変数に対してテンプレートシステムが使用する文字列です。デフォルトは空文字列です。
詳しくは 無効な変数の扱い を参照してください。
'file_charset': ディスク上のテンプレートファイルを読み込む際に使用する文字セットです。デフォルトは
'utf-8'です。'libraries': テンプレートエンジンに登録するテンプレートタグモジュールのラベルとドット区切りPythonパスの辞書。これは新しいライブラリを追加したり、既存のライブラリの代替ラベルを提供するために使用できます。たとえば:OPTIONS = { "libraries": { "myapp_tags": "path.to.myapp.tags", "admin.urls": "django.contrib.admin.templatetags.admin_urls", }, }{% load %}タグに対応する辞書のキーを渡すことでライブラリをロードできます。'builtins': ビルトイン に追加するテンプレートタグモジュールのドット区切りPythonパスのリストです。たとえば:OPTIONS = { "builtins": ["myapp.builtins"], }{% load %}タグを呼び出さなくても、組み込みライブラリのタグやフィルタを使うことができます。
- class Jinja2Link to this definition
Jinja2 がインストールされている必要があります:
Linux / macOS
$ python -m pip install Jinja2
Windows
...\> py -m pip install Jinja2
Jinja2 エンジンを指定するには BACKEND に 'django.template.backends.jinja2.Jinja2' を設定します。
APP_DIRS が True の場合、 Jinja2 エンジンはインストールされているアプリケーションの jinja2 サブディレクトリにあるテンプレートを探します。
OPTIONS の中で最も重要なエントリは 'environment' です。これはJinja2の環境を返す呼び出し可能オブジェクトへのPythonのドット区切りパスです。デフォルトは 'jinja2.Environment' です。Django はその呼び出し可能オブジェクトを起動し、他のオプションをキーワード引数として渡します。さらに、 Django はいくつかのオプションに Jinja2 とは異なるデフォルトを追加します:
'autoescape':True'auto_reload':settings.DEBUG'undefined':DebugUndefined if settings.DEBUG else Undefined
また、 Jinja2 エンジンは以下の OPTIONS も受け付けます:
'context_processors': リクエストでテンプレートがレンダリングされるときにコンテキストを生成するために使用される呼び出し可能オブジェクトへの Python のドット区切りパスのリストです。これらの呼び出し可能オブジェクトはリクエストオブジェクトを引数として取り、コンテキストにマージされるアイテムのdictを返します。デフォルトは空のリストです。
The default configuration is purposefully kept to a minimum. If a template is
rendered with a request (e.g. when using render()),
the Jinja2 backend adds the globals request, csrf_input, and
csrf_token to the context. Apart from that, this backend doesn't create a
Django-flavored environment. It doesn't know about Django filters and tags.
In order to use Django-specific APIs, you must configure them into the
environment.
たとえば、下記のような内容の myproject/jinja2.py を作成することができ、:
from django.templatetags.static import static
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update(
{
"static": static,
"url": reverse,
}
)
return env
これで 'environment' オプションを 'myproject.jinja2.environment' に設定できます。
そして、Jinja2 テンプレートで以下の構文を使用できるようになります:
<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">
<a href="{{ url('admin:index') }}">Administration</a>
タグとフィルタの概念は Django テンプレート言語にも Jinja2 にもありますが、使い方が異なります。Jinja2 はテンプレートの呼び出し可能オブジェクトに引数を渡すことをサポートしているので、 Django テンプレートでテンプレートタグやフィルタを必要とする多くの機能は、上の例のように Jinja2 テンプレートで関数を呼び出すことで実現できます。Jinja2 のグローバル名前空間はテンプレートコンテキストプロセッサの必要性をなくします。Django テンプレート言語には Jinja2 のテストに等価なものはありません。
CommentsLink to this heading#
コメントはこのように書きます:
{% comment %}タグで複数行のコメントを書けます。