テンプレート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

変数は、コンテキストから値を出力します。コンテキストは、キーと値をマッピングする辞書のようなオブジェクトです。

変数はこのように {{}} で囲まれます:

Django template
My first name is {{ first_name }}. My last name is {{ last_name }}.

コンテキストが {'first_name': 'John', 'last_name': 'Doe'} の場合、このテンプレートは次のようにレンダリングされます:

Django template
My first name is John. My last name is Doe.

辞書ルックアップ、属性ルックアップ、リストインデックスルックアップはドット記法で実装されています:

Django template
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}

変数が呼び出し可能オブジェクトに解決される場合、テンプレート・システムは引数なしで呼び出し、呼び出し可能オブジェクトの代わりにその結果を使用します。

タグLink to this heading

タグはレンダリングプロセスにおいて任意のロジックを提供します。

この定義は意図的に曖昧にしてあります。たとえば、タグはコンテンツを出力したり、 "if" 文や "for" ループなどの制御構造として提供したり、データベースからコンテンツを取得したり、あるいは他のテンプレートタグへのアクセスを可能にしたりすることができます。

タグはこのように {%%} で囲まれます:

Django template
{% csrf_token %}

ほとんどのタグは引数を受け付けます:

Django template
{% cycle 'odd' 'even' %}

タグによっては開始タグと終了タグが必要です:

Django template
{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

関連項目: 組み込みタグのリファレンス独自のテンプレートタグの書き方

フィルタLink to this heading

フィルタは変数やタグの引数の値を変換します。

たとえばこのようなものです:

Django template
{{ django|title }}

コンテキストを {'django': 'the web framework for perfectionists with deadlines'} とすると、このテンプレートは次のようにレンダリングされます:

Django template
The Web Framework For Perfectionists With Deadlines

引数を必要とするフィルタもあります:

Django template
{{ my_date|date:"Y-m-d" }}

関連項目: 組み込みフィルタのリファレンス独自のテンプレートフィルタの書き方

CommentsLink to this heading

コメントはこのように書きます:

Django template
{# this won't be rendered #}

{% comment %} タグで複数行のコメントを書けます。

コンポーネント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.Templatedjango.template.Template を一般的なテンプレート API に適応させるための薄いラッパーです。

コンテキストLink to this heading

django.template.Context はコンテキストデータの他にいくつかのメタデータを保持します。これはテンプレートをレンダリングするために Template.render() に渡されます。

django.template.RequestContextContext のサブクラスで、現在の 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 には、以下のように便利な値がいくつか設定されます。

Code
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            # ... some options here ...
        },
    },
]

BACKEND は、Django テンプレートバックエンド API を実装したテンプレートエンジンのクラスへの、ドット区切りの Python path です。ビルトインのバックエンドは、django.template.backends.django.DjangoTemplatesdjango.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 を渡します。

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) を含むタプルのリストです。ここで originorigin-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 設定は次のようになっています。

Code
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つのディレクトリのルートレベルに保存すると、面倒なことになります。

サブディレクトリ内のテンプレートを読み込むには、次のようにスラッシュを使います:

Code
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 です。テンプレートの検索はそのエンジンに制限されます。

使用例:

Code
from django.template.loader import render_to_string

rendered = render_to_string("my_template.html", {"foo": "bar"})

render() ショートカットも参照してください。このショートカットは render_to_string() を呼び出して、その結果をビューから返すのに適した HttpResponse に出力します。

最後に、設定されたエンジンを直接使用することもできます:

enginesLink to this definition

テンプレートエンジンは django.template.engines で利用できます:

Code
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_DIRSTrue の場合、 DjangoTemplates エンジンはインストールされたアプリケーションの templates サブディレクトリにあるテンプレートを探します。この一般名は後方互換性のために残されています。

DjangoTemplates エンジンは以下の OPTIONS を受け付けます:

  • 'autoescape': HTMLのオートエスケープを有効にするかどうかをコントロールする真偽値です。

    デフォルトは True です。

  • 'context_processors': リクエストでテンプレートがレンダリングされるときにコンテキストを生成するために使用される呼び出し可能オブジェクトへの Python のドット区切りパスのリストです。これらの呼び出し可能オブジェクトはリクエストオブジェクトを引数として取り、コンテキストにマージされるアイテムの dict を返します。

    デフォルトは空のリストです。

    詳しくは RequestContext を参照してください。

  • 'debug': テンプレートのデバッグモードのオン/オフを切り替える真偽値です。もし True なら、テンプレートのレンダリング中に例外が発生した場合、fancy エラーページに詳細なレポートが表示されます。このレポートには、該当する行がハイライトされたテンプレートのスニペットが含まれます。

    デフォルトは DEBUG 設定の値です。

  • 'loaders': テンプレートローダクラスへの Python のドット区切りパスのリストです。各 Loader クラスは特定のソースからテンプレートをインポートする方法を知っています。任意で、文字列の代わりにタプルを使うこともできます。タプルの最初の項目は Loader クラス名で、それ以降の項目は初期化時に Loader に渡されます。

    デフォルトは DIRSAPP_DIRS の値に依存します。

    詳しくは ローダーの種類 を参照してください。

  • 'string_if_invalid': 無効な(例えばスペルミスのある)変数に対してテンプレートシステムが使用する文字列です。

    デフォルトは空文字列です。

    詳しくは 無効な変数の扱い を参照してください。

  • 'file_charset': ディスク上のテンプレートファイルを読み込む際に使用する文字セットです。

    デフォルトは 'utf-8' です。

  • 'libraries': テンプレートエンジンに登録するテンプレートタグモジュールのラベルとドット区切りPythonパスの辞書。これは新しいライブラリを追加したり、既存のライブラリの代替ラベルを提供するために使用できます。たとえば:

    Code
    OPTIONS = {
        "libraries": {
            "myapp_tags": "path.to.myapp.tags",
            "admin.urls": "django.contrib.admin.templatetags.admin_urls",
        },
    }
    

    {% load %} タグに対応する辞書のキーを渡すことでライブラリをロードできます。

  • 'builtins': ビルトイン に追加するテンプレートタグモジュールのドット区切りPythonパスのリストです。たとえば:

    Code
    OPTIONS = {
        "builtins": ["myapp.builtins"],
    }
    

    {% load %} タグを呼び出さなくても、組み込みライブラリのタグやフィルタを使うことができます。

class Jinja2Link to this definition

Jinja2 がインストールされている必要があります:

Linux / macOS

Shell
$ python -m pip install Jinja2

Windows

Windows
...\> py -m pip install Jinja2

Jinja2 エンジンを指定するには BACKEND'django.template.backends.jinja2.Jinja2' を設定します。

APP_DIRSTrue の場合、 Jinja2 エンジンはインストールされているアプリケーションの jinja2 サブディレクトリにあるテンプレートを探します。

OPTIONS の中で最も重要なエントリは 'environment' です。これはJinja2の環境を返す呼び出し可能オブジェクトへのPythonのドット区切りパスです。デフォルトは 'jinja2.Environment' です。Django はその呼び出し可能オブジェクトを起動し、他のオプションをキーワード引数として渡します。さらに、 Django はいくつかのオプションに Jinja2 とは異なるデフォルトを追加します:

  • 'autoescape': True

  • 'loader': DIRSAPP_DIRS に設定されたローダー。

  • 'auto_reload': settings.DEBUG

  • 'undefined': DebugUndefined if settings.DEBUG else Undefined

また、 Jinja2 エンジンは以下の OPTIONS も受け付けます:

  • 'context_processors': リクエストでテンプレートがレンダリングされるときにコンテキストを生成するために使用される呼び出し可能オブジェクトへの Python のドット区切りパスのリストです。これらの呼び出し可能オブジェクトはリクエストオブジェクトを引数として取り、コンテキストにマージされるアイテムの dict を返します。

    デフォルトは空のリストです。

デフォルトの設定は意図的に最小限に抑えられています。テンプレートがリクエストと共にレンダリングされる場合 (例えば render() を使用する場合)、 Jinja2 バックエンドは requestcsrf_input および csrf_token というグローバルをコンテキストに追加します。それ以外は、このバックエンドは Django フレーバーの環境を作りません。Django のフィルタやタグについては知りません。Django 固有の API を使うには、環境に設定する必要があります。

たとえば、下記のような内容の myproject/jinja2.py を作成することができ、:

Code
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 テンプレートで以下の構文を使用できるようになります:

Html Jinja
<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 のテストに等価なものはありません。