Python プログラマのための Django テンプレート言語ガイド

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) では、コンテキストから値を取り 出して変数という「穴」に埋め、全てのブロックタグを実行します。

テンプレートシステムの利用

class 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 にあります。コンテキストクラスのコンストラクタ は二つの (省略可能な) 引数をとります:

  • 変数名と変数値を対応づける辞書
  • 現在のアプリケーション名。このアプリケーション名は 名前空間による URL の解決 で役立ちます。もし名前空間化 された URL を使用していなければ、この引数は無視して問題ありません。

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."
Django 1.3 で変更されました: 以前は、呼び出し可能オブジェクトは「ある変数の属性として照合された場合 にだけ」テンプレートシステムから呼び出されていました。この仕様は、 照合方法に一貫性を持たせるために変更されました。

呼び出し可能な変数の場合、ただ照会すれば良い普通の変数に比べるとちょっと 複雑になります。いくつか心に留めておくべきことを挙げておきます:

  • もし変数呼び出し時に例外が送出された場合、その例外に 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 }}
    
  • Django 1.4 で新たに登場しました: ときにはデータ変更を防ぐ以外の目的で、この機能を無効化してテンプレート システムから変数を一切呼び出さないで欲しいと思うこともあるでしょう。 そうするには、その呼び出し可能オブジェクトに 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 を有効にするのは特定のテ ンプレートに対する問題を解決したいときだけにして、デバッグが終わったら すぐに無効にしておくべきです。

コンテキストオブジェクトの操作

class 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()
exception 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 をスタック的に使うと、後述するカスタムテンプレートタグで便利な ことがあります。

コンテキストのサブクラス: RequestContext

class django.template.RequestContext

Django には django.template.RequestContext という特別なコンテキストクラ スがあります。このクラスは通常の django.template.Context とは少し異なる 部分があります。まず、 RequestContext は第一引数に HttpRequest をとります。例えば:

c = RequestContext(request, {
    'foo': 'bar',
})

第二に、 RequestContextTEMPLATE_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")
Django 1.2 で新たに登場しました: これらに加えて RequestContext は常に django.core.context_processors.csrf を使用します。これはセキュリティ関係 のコンテキストプロセッサで、admin やその他の contrib アプリケーションが 必要としており、そして誤って設定ミスをした場合に備えて意図的にハードコードさ れていて、 TEMPLATE_CONTEXT_PROCESSORS の設定で無効化できません。
Django 1.2 で新たに登場しました: 'messages' コンテキストプロセッサが追加されました。詳細については メッセージフレームワーク を参照してください。
Django 1.2 で変更されました: auth コンテキストプロセッサは django.core.context_processors.auth から django.contrib.auth.context_processors.auth へと移動しました。

各プロセッサはタプルに列挙した順に適用されます。従って、あるプロセッサが ある変数をコンテキストに入れた後、別のプロセッサが同じ名前の変数を入れれば、 後者が前者の内容を上書きします。デフォルトのプロセッサについては後で説明し ます。

コンテキストプロセッサが適用されるタイミング

RequestContext には、最初にあなた自身が提供する変数がまず追加され、 その後にコンテキストプロセッサの提供する変数が追加されます。したがって、 コンテキストプロセッサはあなたが提供した変数を上書きする可能性がありますの で、コンテキストプロセッサが提供する変数と同じ変数名を避けるよう気をつけて ください。

RequestContext にはオプションの第三引数 processors に追加のプロセッ サのリストを指定できます。下記の例では、 RequestContextip_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))

各デフォルトプロセッサの動作を以下に示します:

django.contrib.auth.context_processors.auth

このプロセッサが TEMPLATE_CONTEXT_PROCESSORS にある場合、以下の 3 つの変数が RequestContext に入ります:

  • user – 現在ログインしているユーザを表す auth.User インスタン ス (クライアントがログインしていない場合には AnonymousUser インス タンス) です。
  • perms – 現在ログインしているユーザが有しているパーミッションを表 す、 django.contrib.auth.context_processors.PermWrapper のインス タンスです。
Django 1.2 で変更されました: このコンテキストプロセッサは django.core.context_processors.auth から現在の場所に移動されました。
Django 1.3 で変更されました: バージョン 1.3 より前では、 PermWrapperdjango.contrib.auth.context_processors にありました。

django.core.context_processors.debug

このプロセッサが TEMPLATE_CONTEXT_PROCESSORS にある場合、以下の 2 つの変数が RequestContext に入ります。ただし、 DEBUG の設定が True で、リクエストの IP アドレス (request.META['REMOTE_ADDR']) が INTERNAL_IPS 設定に入っている場合だけです:

  • debugTrue です。 DEBUG モードかどうかをテスト するのに使えます。
  • sql_queries{'sql': ..., 'time': ...} 辞書のリストです。 このリストはリクエスト処理中に実行された SQL クエリと、それにかかった 時間を表しています。リストはクエリの実行順にならんでいます。

django.core.context_processors.i18n

このプロセッサが TEMPLATE_CONTEXT_PROCESSORS にある場合、以下の 2 つの変数が RequestContext に入ります:

  • LANGUAGESLANGUAGES 設定の値です。
  • LANGUAGE_CODErequest.LANGUAGE_CODE が存在する場合、その値 です。値がなければ LANGUAGE_CODE 設定の値になります。

詳しくは 国際化とローカライズ を参照してください。

django.core.context_processors.media

TEMPLATE_CONTEXT_PROCESSORS にこのコンテキストプロセッサを入れる と、 RequestContextMEDIA_URL というコンテキスト変数が入ります。 MEDIA_URL には MEDIA_URL 設定の値が入っています。

django.core.context_processors.static

django.core.context_processors.static()
Django 1.3 で新たに登場しました: リリースノートを参照してください

TEMPLATE_CONTEXT_PROCESSORS にこのコンテキストプロセッサを入れる と、 RequestContextSTATIC_URL というコンテキスト変数が入ります。 STATIC_URL には STATIC_URL 設定の値が入っています。

django.core.context_processors.csrf

Django 1.2 で新たに登場しました: リリースノートを参照してください

このコンテキストプロセッサは csrf_token テンプレートタグが クロスサイトリクエストフォージェリ 対策のために 必要とするトークンを追加します。

django.core.context_processors.request

このプロセッサが TEMPLATE_CONTEXT_PROCESSORS にある場合、変数 requestRequestContext に入ります。この変数は現在の HttpRequest を表現します。このプロセッサはデフォルト では有効でないので注意してください。利用したければ有効にせねばなりません。

django.contrib.messages.context_processors.messages

このプロセッサが TEMPLATE_CONTEXT_PROCESSORS にある場合、変数が 一つ RequestContext に追加されます:

  • messages – ユーザモデルを通して (user.message_set.create を使って) 設定されたか、 メッセージフレームワーク を 通して設定されたメッセージ (文字列) のリスト。
Django 1.2 で新たに登場しました: このテンプレートコンテキスト変数はこれまで '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 設定を使ってどのディレクトリに テンプレートが収められているかを指定してください。この値は文字列のリストか タプルで指定します。文字列にはテンプレートディレクトリへの完全なパスを指定 せねばなりません。例えば:

TEMPLATE_DIRS = (
    "/home/html/templates/lawrence.com",
    "/home/html/templates/default",
)

Web サーバがテンプレートディレクトリの中身を読みだせる限り、テンプレートは どこにでも置けます。拡張子はなんでもよく、 .html でも .txt でも かまいませんし、拡張子を付けなくてもかまいません。

Windows を使っている場合でも、パスは Unix 形式のスラッシュを使った表記法で 指定せねばならないので注意して下さい。

Python API

Django でファイルからテンプレートを読み出すには二通りの方法があります:

django.template.loader.get_template(template_name)

get_template は、指定した名前のテンプレートに対応したコンパイル済み のテンプレート (Template オブジェクト) を返します。テンプレートが存 在しなければ django.template.TemplateDoesNotExist を送出します。

django.template.loader.select_template(template_name_list)

select_templateget_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

Loader 型

デフォルトでは、 Django はファイルシステムベースのテンプレートローダを使っ ていますが、 Django には他のテンプレートローダも付属しており、その他のデー タソースからテンプレートをロードできるようになっています。

ファイルシステムベース以外のテンプレートローダはデフォルトでは無効化されて いますが、 TEMPLATE_LOADERS 設定を編集して有効にできます。 TEMPLATE_LOADERS は文字列のタプルで、各文字列がテンプレートロー ダクラスを表します。組み込みのテンプレートローダを以下に示します:

Django 1.2 で変更されました: 1.2 より前の Django ではテンプレートローダは呼び出し可能オブジェクト (普通 は関数) をベースにしていましたが、 1.2 リリースからは新しいクラスベースの API が提供され、以下で説明するすべてのローダーはこの新しい API を実装して います。
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 のインスタンスは、以後の同一テンプレートに対するリクエストで返されます。

たとえば、 filesystemapp_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.loaderrender_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 はリスト中で最初に現れた、存在するテンプレートを使用します) をとります。また、オプション引数を二つとります:

dictionary
テンプレートのコンテキストとして使う値の入った辞書です。第二固定引 数として渡しても構いません。
context_instance
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 1.2 で新たに登場しました: リリースノートを参照してください

Django の Template クラスと Loader クラスはテンプレートをロード・レンダ リングするためのシンプルな API を実装しています。この API を実装するシンプルな ラッパークラスを提供すれば、 Jinja2Cheetah といったサードパーティのテンプレートシステ ムを使用することも可能です。こうすることで、 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 の他の機能を使いつつ、異なるテンプレート言語で すべてのテンプレートを書けるようになりました。