revision-up-to: | 11321 (1.1) unfinished |
---|
このドキュメントでは、 Django のテンプレートシステムを技術的な側面、すなわ ちどのように動作し、どうやって拡張するかという観点から解説します。テンプレー ト言語の構文リファレンスを探しているのなら、 Django テンプレート言語 を参照 してください。
Django テンプレートシステムを他のアプリケーションの部品として使いたい場合、 すなわち Django フレームワークの他の部分は必要ない場合、このドキュメントの 後の方にある 設定 の節に必ず目を 通して下さい。
テンプレート (template) とは、 Django テンプレート言語を使ってマークアッ プしたテキストドキュメントや Python 文字列です。テンプレートには ブロックタグ (block tag) や 変数 (variable) を入れられます。
ブロックタグ はテンプレート中で何らかの処理を行う部分を表すシンボルです。
とはいえ、この定義はいささか曖昧ですね。例えば、ブロックタグを使うと、何ら かのコンテンツを出力したり、制御構造 (“if” 文や “for” ループ) を記述したり、 データベースからコンテンツを取り出したり、他のテンプレートタグにアクセスし たりします。
ブロックタグは "{%"
と "%}"
で囲みます。
ブロックタグを使ったテンプレートの例を示します:
{% if is_logged_in %}Thanks for logging in!{% else %}Please log in.{% endif %}
変数 はテンプレート中で何らかの値を出力する部分を表すシンボルです。
変数は "{{"
と "}}"
で囲みます。
変数を使ったテンプレートの例を示します。:
My first name is {{ first_name }}. My last name is {{ last_name }}.
コンテキスト (context) はテンプレートに渡される「変数名」から「変数の値」 へのマッピングです。
テンプレートの レンダリング (rendering) では、コンテキストから値を取り 出して変数という「穴」に埋め、全てのブロックタグを実行します。
django.template.
Template
¶Python でテンプレートを使うには、以下の 2 段階のプロセスを踏みます:
Template
オブジェクトを生成しま
す。Template
オブジェクトの render()
メ
ソッドを呼び出します。Template
オブジェクトを作成するには、直接インスタンスを生成する方法が最
も簡単です。 Template
クラスは django.template.Template
にあります。
コンストラクタは引数に生のテンプレートコードを取ります:
>>> from django.template import Template
>>> t = Template("My name is {{ my_name }}.")
>>> print t
<django.template.Template instance>
舞台裏
このシステムは Template
オブジェクトを生成するときに生のテンプレー
トコードを一度しか解析しません。コンパイル後のテンプレートはパフォーマ
ンス上の目的から “node” データ構造に保存されます。
テンプレートコードの解析自体もきわめて高速です。解析のほとんどは短い正 規表現を一つ呼び出すだけで終わります。
render
(context)¶コンパイル済みの Template
オブジェクトを作成したら、オブジェクトを使っ
てコンテキストをレンダリングできるようになります。 Context
クラスは
django.template.Context
にあります。コンテキストクラスのコンストラクタ
は二つの (省略可能な) 引数をとります:
Template
オブジェクトの render()
メソッドを呼び出すと、コンテキス
トの値でテンプレートを「埋め」て出力します:
>>> from django.template import Context, Template
>>> t = Template("My name is {{ my_name }}.")
>>> c = Context({"my_name": "Adrian"})
>>> t.render(c)
"My name is Adrian."
>>> c = Context({"my_name": "Dolores"})
>>> t.render(c)
"My name is Dolores."
変数名には、任意の文字 (A-Z)、数字 (0-9)、アンダースコアまたはドットしか 使えません (ただしアンダースコアで始めてはいけません)。
ドットはテンプレートレンダリングにおいて特殊な意味を持ちます。変数名中の ドットは、 値の照合 (lookup) を意味します。もっと詳しく言えば、テンプレー トシステムが変数名中にドットを見つけた場合、以下の順で値の照合を試みます:
foo["bar"]
のような辞書としての照合。foo.bar
のような属性値の照合。foo[bar]
のようなリストのインデクス指定。テンプレートシステムは最初に成功した照合結果を使います。いわば短絡的ロジッ ク (short-circuit logic) です。いくつか例を示します:
>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."
>>> class PersonClass: pass
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."
>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."
もし変数 (のいずれかの部分) が呼び出し可能オブジェクト (callable) である場合、 テンプレートシステムはそれを呼び出そうとします。たとえば:
>>> class PersonClass2:
... def name(self):
... return "Samantha"
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."
呼び出し可能な変数の場合、ただ照会すれば良い普通の変数に比べるとちょっと 複雑になります。いくつか心に留めておくべきことを挙げておきます:
もし変数呼び出し時に例外が送出された場合、その例外に
silent_variable_failure
という属性があり、かつ値が True``に設
定されている場合を除き、例外はそのまま伝播します。例外が
``silent_variable_failure
という属性を持つ場合、変数は空文字列にレ
ンダリングされます。例えば:
>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClass3:
... def first_name(self):
... raise AssertionError, "foo"
>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
...
AssertionError: foo
>>> class SilentAssertionError(Exception):
... silent_variable_failure = True
>>> class PersonClass4:
... def first_name(self):
... raise SilentAssertionError
>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
"My name is ."
全ての Django データベース API の DoesNotExist
例外の基底クラスで
ある django.core.exceptions.ObjectDoesNotExist
では
silent_variable_failure = True
になっているので注意してください。
つまり、 Django テンプレートと Django モデルオブジェクトを使っている
限り、 DoesNotExist
例外が出ても暗黙のうちに失敗するだけなのです。
言うまでもないことですが、呼び出すと副作用を起こす変数もあります。 副作用のある変数にテンプレートからアクセスできるようにしておくと、 間抜けな結果になったりセキュリティホールを作ったりしてしまうことがある ので注意して下さい。
分かりやすい例に、 Django モデルオブジェクトの
delete()
メソッドがあります。テンプレート
システムでは、以下のような書き方を許すべきではありません:
大事なデータを消しちゃいますよ。 {{ data.delete }}
do_not_call_in_templates
属性を設定し、その値を True
にします。こうするとテンプレートシステムは
あたかもその変数が呼び出し可能オブジェクトではない場合と同じように扱います
(その呼び出し可能オブジェクトの属性へのアクセスなども可能になります)。基本的に、変数が存在しなければ、 テンプレートシステムは
TEMPLATE_STRING_IF_INVALID
の設定値を挿入します。この値のデフォルトは
''
(空文字列) です。
無効な値に対してフィルタが適用されるのは、
TEMPLATE_STRING_IF_INVALID
の値が ''
に設定されている場合だ
けです。 TEMPLATE_STRING_IF_INVALID
が ''
以外の値になってい
ると、フィルタは無視されます。
ただし、 if
, for
, regroup
といったテンプレートタグの中では、少
し違った挙動になります。これらのテンプレートタグ中では、無効な値は None
であると解釈されます。また、これらのテンプレートタグ中のフィルタは、無効な
値に対しも常に適用されます。
TEMPLATE_STRING_IF_INVALID
にフォーマット指示文字の '%s'
が
入っている場合、 '%s'
は不正な変数の変数名で置き換えられます。
デバッグ専用です!
TEMPLATE_STRING_IF_INVALID
はデバッグには便利ですが、「開発
時のデフォルトの設定」としてオンにするのはよい考えではありません。
Admin サイトのテンプレートをはじめとする多くのテンプレートは、実在し
ない値を呼び出しても何も出力しないという動作を前提に作られています。
''
以外の値を TEMPLATE_STRING_IF_INVALID
に指定した場合、
こうしたテンプレートやサイトのレンダリングで問題が生じるかもしれません。
一般に、 TEMPLATE_STRING_IF_INVALID
を有効にするのは特定のテ
ンプレートに対する問題を解決したいときだけにして、デバッグが終わったら
すぐに無効にしておくべきです。
django.template.
Context
¶皆さんはほとんどの場合、全ての値を入れた辞書を Context()
に渡して
Context
オブジェクトのインスタンスを生成していることでしょう。しかし、
Context
オブジェクトはインスタンス化した後にも、通常の辞書と同じように
値を追加したり削除したりできます:
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
''
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
pop
()¶push
()¶django.template.
ContextPopException
¶Context
オブジェクトは一種のスタックです。すなわち、 push()
や
pop()
操作を行えます。 pop()
しすぎると、
django.template.ContextPopException
を送出します:
>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.push()
>>> c['foo'] = 'second level'
>>> c['foo']
'second level'
>>> c.pop()
>>> c['foo']
'first level'
>>> c['foo'] = 'overwritten'
>>> c['foo']
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
django.template.ContextPopException
update
(other_dict)¶push()
と pop()
に加え、 Context
オブジェクトは update()
メソッドも定義しています。これは push()
と同じように動作しますが、
空の辞書ではなく引数で受け取った辞書をスタックに追加します。
>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'foo': 'updated'})
{'foo': 'updated'}
>>> c['foo']
'updated'
>>> c.pop()
{'foo': 'updated'}
>>> c['foo']
'first level'
Context
をスタック的に使うと、後述するカスタムテンプレートタグで便利な
ことがあります。
django.template.
RequestContext
¶Django には django.template.RequestContext
という特別なコンテキストクラ
スがあります。このクラスは通常の django.template.Context
とは少し異なる
部分があります。まず、 RequestContext
は第一引数に
HttpRequest
をとります。例えば:
c = RequestContext(request, {
'foo': 'bar',
})
第二に、 RequestContext
は TEMPLATE_CONTEXT_PROCESSORS
設定
に従っていくつかの値を自動的にコンテキストに入れます。
TEMPLATE_CONTEXT_PROCESSORS
設定は呼び出し可能オブジェクトのタプルになっ
ています。個々の呼び出し可能オブジェクトは コンテキストプロセッサ と呼
ばれ、リクエストオブジェクトを引数にとって。何らかの値を要素に持った辞書を
返します。この辞書はコンテキストオブジェクトに統合されます。デフォルトでは、
TEMPLATE_CONTEXT_PROCESSORS
は以下のようになっています:
("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.contrib.messages.context_processors.messages")
RequestContext
は常に
django.core.context_processors.csrf
を使用します。これはセキュリティ関係
のコンテキストプロセッサで、admin やその他の contrib アプリケーションが
必要としており、そして誤って設定ミスをした場合に備えて意図的にハードコードさ
れていて、 TEMPLATE_CONTEXT_PROCESSORS
の設定で無効化できません。'messages'
コンテキストプロセッサが追加されました。詳細については
メッセージフレームワーク を参照してください。django.core.context_processors.auth
から
django.contrib.auth.context_processors.auth
へと移動しました。各プロセッサはタプルに列挙した順に適用されます。従って、あるプロセッサが ある変数をコンテキストに入れた後、別のプロセッサが同じ名前の変数を入れれば、 後者が前者の内容を上書きします。デフォルトのプロセッサについては後で説明し ます。
コンテキストプロセッサが適用されるタイミング
RequestContext
には、最初にあなた自身が提供する変数がまず追加され、
その後にコンテキストプロセッサの提供する変数が追加されます。したがって、
コンテキストプロセッサはあなたが提供した変数を上書きする可能性がありますの
で、コンテキストプロセッサが提供する変数と同じ変数名を避けるよう気をつけて
ください。
RequestContext
にはオプションの第三引数 processors
に追加のプロセッ
サのリストを指定できます。下記の例では、 RequestContext
に
ip_address
変数が入ります:
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']}
def some_view(request):
# ...
c = RequestContext(request, {
'foo': 'bar',
}, [ip_address_processor])
return HttpResponse(t.render(c))
Note
Django の render_to_response()
ショートカットを
使っていて、辞書オブジェクトを渡してコンテキストの変数を追加している場合、
テンプレートはデフォルトで (RequestContext
ではなく) Context
になります。テンプレートのレンダリングに RequestContext
を使うには、
render_to_response()
の 3 つめの引数に
RequestContext
インスタンスを指定します。
コードは以下のようになるでしょう:
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
各デフォルトプロセッサの動作を以下に示します:
このプロセッサが TEMPLATE_CONTEXT_PROCESSORS
にある場合、以下の
3 つの変数が RequestContext
に入ります:
user
– 現在ログインしているユーザを表す auth.User
インスタン
ス (クライアントがログインしていない場合には AnonymousUser
インス
タンス) です。perms
– 現在ログインしているユーザが有しているパーミッションを表
す、 django.contrib.auth.context_processors.PermWrapper
のインス
タンスです。django.core.context_processors.auth
から現在の場所に移動されました。PermWrapper
は
django.contrib.auth.context_processors
にありました。このプロセッサが TEMPLATE_CONTEXT_PROCESSORS
にある場合、以下の
2 つの変数が RequestContext
に入ります。ただし、 DEBUG
の設定が
True
で、リクエストの IP アドレス (request.META['REMOTE_ADDR']
) が
INTERNAL_IPS
設定に入っている場合だけです:
debug
– True
です。 DEBUG
モードかどうかをテスト
するのに使えます。sql_queries
– {'sql': ..., 'time': ...}
辞書のリストです。
このリストはリクエスト処理中に実行された SQL クエリと、それにかかった
時間を表しています。リストはクエリの実行順にならんでいます。このプロセッサが TEMPLATE_CONTEXT_PROCESSORS
にある場合、以下の
2 つの変数が RequestContext
に入ります:
LANGUAGES
– LANGUAGES
設定の値です。LANGUAGE_CODE
– request.LANGUAGE_CODE
が存在する場合、その値
です。値がなければ LANGUAGE_CODE
設定の値になります。詳しくは 国際化とローカライズ を参照してください。
TEMPLATE_CONTEXT_PROCESSORS
にこのコンテキストプロセッサを入れる
と、 RequestContext
に MEDIA_URL
というコンテキスト変数が入ります。
MEDIA_URL
には MEDIA_URL
設定の値が入っています。
django.core.context_processors.
static
()¶リリースノートを参照してください
TEMPLATE_CONTEXT_PROCESSORS
にこのコンテキストプロセッサを入れる
と、 RequestContext
に STATIC_URL
というコンテキスト変数が入ります。
STATIC_URL
には STATIC_URL
設定の値が入っています。
リリースノートを参照してください
このコンテキストプロセッサは csrf_token
テンプレートタグが
クロスサイトリクエストフォージェリ 対策のために
必要とするトークンを追加します。
このプロセッサが TEMPLATE_CONTEXT_PROCESSORS
にある場合、変数
request
が RequestContext
に入ります。この変数は現在の
HttpRequest
を表現します。このプロセッサはデフォルト
では有効でないので注意してください。利用したければ有効にせねばなりません。
このプロセッサが TEMPLATE_CONTEXT_PROCESSORS
にある場合、変数が
一つ RequestContext
に追加されます:
messages
– ユーザモデルを通して (user.message_set.create
を使って)
設定されたか、 メッセージフレームワーク を
通して設定されたメッセージ (文字列) のリスト。'auth'
コンテキストプロセッサ
が提供してきました。後方互換性のため 'auth'
コンテキストプロセッサは
Django 1.4 までは messages
変数を提供し続けます。もし messages
変数を使う場合、あなたのプロジェクトはどちらの (または両方の) コンテキスト
プロセッサを使っても動作するでしょうけれども、将来のアップグレードに備えて
django.contrib.messages.context_processors.messages
を追加することを
推奨します。コンテキストプロセッサのインタフェースはとても簡単です。コンテキストプロセッ
サは単なる Python の関数で、 HttpRequest
オブジェクトを
引数にとり、テンプレートコンテキストに追加できるような辞書を返します。
コンテキストプロセッサは、 必ず 辞書型を返さねばなりません。
自分のコードベースに自作のコンテキストプロセッサを入れてもかまいません。
Django 側からは、自作のコンテキストプロセッサを
TEMPLATE_CONTEXT_PROCESSORS
設定で指定するようにしてください。
一般的には、低水準の Template
API を自分で使うことはほとんどなく、テン
プレートはファイルの形でファイルシステム上に保存することになるでしょう。
テンプレートディレクトリ に指定したディレクトリにテンプレートファイルを
保存してください。
Django はテンプレートローダの設定 (「Loader 型」を参照してください)
に従って、いくつものテンプレートディレクトリを検索しますが、最も基本的なテ
ンプレートディレクトリ指定方法は TEMPLATE_DIRS
を使う方法です。
設定ファイル中で、 TEMPLATE_DIRS
設定を使ってどのディレクトリに
テンプレートが収められているかを指定してください。この値は文字列のリストか
タプルで指定します。文字列にはテンプレートディレクトリへの完全なパスを指定
せねばなりません。例えば:
TEMPLATE_DIRS = (
"/home/html/templates/lawrence.com",
"/home/html/templates/default",
)
Web サーバがテンプレートディレクトリの中身を読みだせる限り、テンプレートは
どこにでも置けます。拡張子はなんでもよく、 .html
でも .txt
でも
かまいませんし、拡張子を付けなくてもかまいません。
Windows を使っている場合でも、パスは Unix 形式のスラッシュを使った表記法で 指定せねばならないので注意して下さい。
Django でファイルからテンプレートを読み出すには二通りの方法があります:
django.template.loader.
get_template
(template_name)¶get_template
は、指定した名前のテンプレートに対応したコンパイル済み
のテンプレート (Template
オブジェクト) を返します。テンプレートが存
在しなければ django.template.TemplateDoesNotExist
を送出します。
django.template.loader.
select_template
(template_name_list)¶select_template
は get_template
と同じです。ただし、テンプレー
ト名のリストを引数にとります。リストの中で最初に見つかったテンプレート
を返します。
例えば get_template('story_detail.html')
を呼び出した場合、前述のような
TEMPLATE_DIRS
の設定をしていれば、Django は以下のような順番でテ
ンプレートファイルを探します:
/home/html/templates/lawrence.com/story_detail.html
/home/html/templates/default/story_detail.html
select_template(['story_253_detail.html', 'story_detail.html'])
なら、
以下の順で探します:
/home/html/templates/lawrence.com/story_253_detail.html
/home/html/templates/default/story_253_detail.html
/home/html/templates/lawrence.com/story_detail.html
/home/html/templates/default/story_detail.html
テンプレートが見つかった時点で Django は検索を停止します。
Tip
select_template()
を使うと、極めて柔軟な「テンプレート構成機能
(templatability)」を実現できます。例えば、あるニュース記事を書いていて、
記事によってはカスタムのテンプレートを使いたいとします。
select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])
のようにすると、個々の記事にカスタムのテンプレートを使いながら、カスタ
ムのテンプレートがない記事に対してはフォールバックのテンプレートを用意
できるというわけです。
テンプレートディレクトリを複数のサブディレクトリで構成するのは可能ですし、 お勧めでもあります。慣習的には各 Django アプリケーション毎にサブディレク トリを作成します。必要に応じてさらにサブディレクトリを作成します。
精神衛生のためにもぜひテンプレートを階層化しましょう。一つのディレクトリの ルートレベルに全てのテンプレートを保存するのは、だらしないことこの上ありま せん。
サブディレクトリ下にあるテンプレートをロードするには、以下のようにスラッシュ を使って指定します:
get_template('news/story_detail.html')
この例の get_template()
は、上の TEMPLATE_DIRS
と同じ設定を
使った場合、以下の順番でテンプレートをロードしようと試みます:
/home/html/templates/lawrence.com/news/story_detail.html
/home/html/templates/default/news/story_detail.html
デフォルトでは、 Django はファイルシステムベースのテンプレートローダを使っ ていますが、 Django には他のテンプレートローダも付属しており、その他のデー タソースからテンプレートをロードできるようになっています。
ファイルシステムベース以外のテンプレートローダはデフォルトでは無効化されて
いますが、 TEMPLATE_LOADERS
設定を編集して有効にできます。
TEMPLATE_LOADERS
は文字列のタプルで、各文字列がテンプレートロー
ダクラスを表します。組み込みのテンプレートローダを以下に示します:
django.template.loaders.filesystem.Loader
TEMPLATE_DIRS
の設定に従って、ファイルシステムからテンプレー
トをロードします。django.template.loaders.app_directories.Loader
ファイルシステム上の Django アプリケーションからテンプレートをロードし
ます。このローダは INSTALLED_APPS
の各アプリケーションについ
て templates
サブディレクトリを探します。ディレクトリが存在すれば、
Django はその中からテンプレートを探します。
これはすなわち、個々のアプリケーションにテンプレートを保存しておけると いうことです。このローダを使うと、 Django アプリケーションをデフォルト のテンプレート付きで配りやすくなります。
例えば、以下のように設定します:
INSTALLED_APPS = ('myproject.polls', 'myproject.music')
get_template('foo.html')
は以下のディレクトリを順番に探します:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
このローダは最初に import した時に最適化処理を行います。すなわち、
INSTALLED_APPS
パッケージリストの中で、 templates
サブディ
レクトリを持つものをキャッシュします。
このローダはデフォルトで有効化されています。
django.template.loaders.eggs.Loader
app_directories
と同じですが、ファイルシステムではなく Python eggs
からテンプレートをロードします。
このローダはデフォルトで無効化されています。
django.template.loaders.cached.Loader
デフォルトでは、テンプレートシステムはレンダリングが必要になるたびにテンプ レートを読み出してコンパイルします。 Django のテンプレートシステムは非常に 高速ですが、読み出しとコンパイルのオーバーヘッドが積み重なっていく可能性は あります。
キャッシュドテンプレートローダ (cached template loader) はクラスベースの
ローダで、ラッピングする他のローダのリストを指定して設定します。ラッピング
されたローダは、未知のテンプレートが初めて現れたときに、その場所を特定する
ために使われます。そしてキャッシュドテンプレートローダはコンパイルされた
Template
をメモリ上に格納します。キャッシュされた Template
のインスタンスは、以後の同一テンプレートに対するリクエストで返されます。
たとえば、 filesystem
と app_directories
テンプレートローダの
テンプレートをキャッシュするには次のように設定します:
TEMPLATE_LOADERS = (
('django.template.loaders.cached.Loader', (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)),
)
Note
すべての組み込み Django テンプレートタグはキャッシュされたローダで
安全に扱えますが、もしサードパーティ製あるいはあなた自身が書いた
カスタムテンプレートタグを使っている場合、各タグの Node
の実装が
スレッドセーフになっていることを確認しておくべきでしょう。詳細について
は、 テンプレートタグのスレッドセーフ性を考慮する を参照してください。
このローダはデフォルトで無効化されています。
Django はテンプレートローダを TEMPLATE_LOADERS
設定の順番に従っ
て試してゆき、マッチするテンプレートが見つかるまで探します。
render_to_string
ショートカット¶django.template.loader.
render_to_string
(template_name, dictionary=None, context_instance=None)¶テンプレートのロードとレンダの反復を減らすため、 Django は作業を自動化する
ためのショートカットとして、 django.template.loader
で
render_to_string()
を提供しています。このショートカットは、テンプレート
をロードし、レンダして、結果を文字列として返します:
from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', { 'foo': 'bar' })
render_to_string
ショートカットは、必須の引数として、レンダリング時にロー
ドするテンプレートの名前 template_name
(またはテンプレート名のリスト。
この場合 Django はリスト中で最初に現れた、存在するテンプレートを使用します)
をとります。また、オプション引数を二つとります:
Context
またはサブクラス (例えば RequestContext
) のインスタ
ンスです。テンプレートのコンテキストとして使われます。第三固定引数
として渡してもかまいません。render_to_response()
ショートカットも参照してくだ
さい。このショートカットは、結果を HttpResponse
に入れて、ビューからレンダ内容を直接返せるようにしています。
Note
この節は、テンプレートシステムを他のアプリケーションの出力用コンポーネ ントとして使ってみたいと考えている人のためのものです。テンプレートシス テムを Django の一部として使っている人には、この節の内容はあてはまりま せん。
通常、 Django は必要な全ての設定情報を、デフォルトの設定ファイル上の設定と
環境変数 DJANGO_SETTING_FILE
に指定したファイル上の設定を合わせ
たものからロードします。ただし、 Django の他の部分からテンプレートシステム
を切り離して使いたい場合は、環境変数を介して設定ファイルを扱うよりも、アプ
リケーション内でテンプレートシステムを初期化したいでしょうから、環境変数を
使う方法はあまり便利とはいえないでしょう。
この問題を解決するためには、 DJANGO_SETTINGS_MODULE を使わない設定方法
に書かれている手動設定の方法を使う必要があります。テンプレートシステムの必
要な部分を import して、何らかのテンプレート関連の関数を呼ぶ 前に 、指定
したい設定を引数にして django.conf.settings.configure()
を呼び出して下さ
い。少なくとも TEMPLATE_DIRS
(テンプレートローダを使いたい場合),
DEFAULT_CHARSET
(通常はデフォルトの utf-8
で十分です),
TEMPLATE_DEBUG
などを設定することになるでしょう。設定可能な変数
は、 設定ファイルのドキュメント に書かれています。関
係のある変数は TEMPLATE_
で始まっている設定です。
リリースノートを参照してください
Django の Template
クラスと Loader
クラスはテンプレートをロード・レンダ
リングするためのシンプルな API を実装しています。この API を実装するシンプルな
ラッパークラスを提供すれば、 Jinja2 や Cheetah といったサードパーティのテンプレートシステ
ムを使用することも可能です。こうすることで、 Context
オブジェクトや
render_to_response()
などの使いやすいショートカットと
いった Django の役立つ機能をあきらめることなくサードパーティのテンプレートライ
ブラリを使うことができます。
Django のテンプレートシステムのコアコンポーネントは Template
クラスです。
このクラスは非常にシンプルなインタフェースを備えています: テンプレート文字列を
指定する引数を一つ取るコンストラクタと、 Context
オブジェクトを受け取りレンダリングされたレスポンスを文字列を返す render()
メソッドです。
たとえば、Context
オブジェクトではなく辞書オブジェクトを受け取るような
render()
メソッドを備えた Template
オブジェクトを定義しているテンプレー
ト言語を私たちが使っているとしましょう。その場合、 Django の Template
のイ
ンタフェースを実装する次のような簡単なラッパーを書くことができます:
import some_template_language
class Template(some_template_language.Template):
def render(self, context):
# flatten the Django Context into a single dictionary.
context_dict = {}
for d in context.dicts:
context_dict.update(d)
return super(Template, self).render(context_dict)
これだけで、私たちの空想の Template
クラスを Django のロード・レンダリングの
システムで使えるようになります!
次のステップは、標準の Template
のかわりに私たちの
カスタムテンプレートクラスのインスタンスを返す Loader
クラスを書くことです。
カスタム Loader
クラスは django.template.loader.BaseLoader
を継承し、
load_template_source()
メソッドをオーバーライドするべきです。このメソッドは
template_name
引数を受け取ってテンプレートをディスク (または他のどこか)
からロードし、次のタプルを返します: (template_string, template_origin)
。
Loader
クラスの load_template()
メソッドは、テンプレート文字列を
load_template_source()
を呼び出して取得し、テンプレートソースから
Template
をインスタンス化して、次のタプルを返します:
(template, template_origin)
。実際には Template
はこのようにインスタンス
化されるので、カスタムテンプレートクラスを代わりに使うためには
load_template_source()
メソッドのオーバーライドが必要、というわけです。
また django.template.loaders.app_directories.Loader
を継承すると、
その load_template_source()
メソッドの実装を利用することもできます:
from django.template.loaders import app_directories
class Loader(app_directories.Loader):
is_usable = True
def load_template(self, template_name, template_dirs=None):
source, origin = self.load_template_source(template_name, template_dirs)
template = Template(source)
return template, origin
最後に、 Django にカスタムローダを使わせるようプロジェクト設定を変更する 必要があります。以上で、 Django の他の機能を使いつつ、異なるテンプレート言語で すべてのテンプレートを書けるようになりました。
Oct 26, 2017