The Django Template Language

このドキュメントはDjangoテンプレートシステムの文法を説明しています。もしあなたがもっと技術者的な観点でどう動かすかやどう拡張するかを知りたい場合は、The Django template language: for Python programmers をご覧ください。

Django のテンプレート言語は、パワーと使いやすさのバランスを取るように設計されています。HTMLでの作業に使用されるものが快適に感じられるように設計されているのです。あなたが他のテキストベースのテンプレート言語に対して SmartyJinja2 のような露出的な処理を習得しているのなら、Django テンプレートをより身近に感じられるはずです。

設計思想

あなたがどんなプログラミング経験を持ってるにしろ、HTMLの中にコードを埋め込む言語を使っていたにしろ、DjangoテンプレートシステムはただHTMLのなかにPythonを貼り付けるだけのシステムではないことを心に留めたいと思われたでしょう。これは"テンプレートシステムは、プログラム論理構造を表すのでなく、あくまでプレゼンテーションを表現することを意味する。"というデザイン設計から来ています。

Django のテンプレートシステムは、いくつかのプログラミング構造 - ブールテスト用の if タグ、ループ用の for タグなどと同様に機能するタグを提供しています。しかしこれらは、単純に対応する Python コードとしては実行するわけではなく、テンプレートシステムは、任意の Python の式を実行しません。タグ、フィルタ、および下の文法リストのみがデフォルトではサポートされています。(しかし、必要に応じて あなた独自の拡張機能 をテンプレート言語に追加することも可能です。)

テンプレート

A template is a text file. It can generate any text-based format (HTML, XML, CSV, etc.).

テンプレートに含まれるのは、テンプレートが読み込まれたとき実際の値で置き換えられる 変数 と、テンプレートのロジックを制御する タグ です。

下は幾つかの基本を示している少ない見本です。各要素については、このドキュメントの後半で説明します。

{% extends "base_generic.html" %}

{% block title %}{{ section.title }}{% endblock %}

{% block content %}
<h1>{{ section.title }}</h1>

{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

設計思想

Why use a text-based template instead of an XML-based one (like Zope's TAL)? We wanted Django's template language to be usable for more than just XML/HTML templates. You can use the template language for any text-based format such as emails, JavaScript and CSV.

変数

Variables look like this: {{ variable }}. When the template engine encounters a variable, it evaluates that variable and replaces it with the result. Variable names consist of any combination of alphanumeric characters and the underscore ("_") but may not start with an underscore, and may not be a number. The dot (".") also appears in variable sections, although that has a special meaning, as indicated below. Importantly, you cannot have spaces or punctuation characters in variable names.

変数の属性にアクセスするには、ドットを ('.') を使用します。

背景

技術的には、テンプレートシステムがドットを検出した際、以下の参照項目をこの順番で実行しようとします:

  • 辞書検索
  • 属性やメソッドの検索
  • 数値のインデックス検索

結果の値が呼び出し可能である場合は、引数なしで呼び出されます。呼び出しの結果は、テンプレートの値となります。

この検索の手順は、辞書検索を上書きするオブジェクトにおいて、予期しない動作を引き起こす可能性があります。例えば、`` collections.defaultdict`` すべてをループ処理をしようとする、次のコードスニペットを考えてみましょう:

{% for k, v in defaultdict.items %}
    Do something with k and v here...
{% endfor %}

最初に辞書検索が行われるため、その挙動が動作してしまい、意図していた .items() メソッドを使用せずに、デフォルト値を提供してしまいます。この場合、最初に辞書を変換することを検討してください。

In the above example, {{ section.title }} will be replaced with the title attribute of the section object.

もし存在しない変数を使いたい場合、テンプレートシステムは`デフォルトで``''`` (the empty string)が置かれている場所に、string_if_invalid` のオプション値を挿入します。

Note that "bar" in a template expression like {{ foo.bar }} will be interpreted as a literal string and not using the value of the variable "bar", if one exists in the template context.

Variable attributes that begin with an underscore may not be accessed as they're generally considered private.

フィルター

You can modify variables for display by using filters.

Filters look like this: {{ name|lower }}. This displays the value of the {{ name }} variable after being filtered through the lower filter, which converts text to lowercase. Use a pipe (|) to apply a filter.

Filters can be "chained." The output of one filter is applied to the next. {{ text|escape|linebreaks }} is a common idiom for escaping text contents, then converting line breaks to <p> tags.

Some filters take arguments. A filter argument looks like this: {{ bio|truncatewords:30 }}. This will display the first 30 words of the bio variable.

Filter arguments that contain spaces must be quoted; for example, to join a list with commas and spaces you'd use {{ list|join:", " }}.

Django provides about sixty built-in template filters. You can read all about them in the built-in filter reference. To give you a taste of what's available, here are some of the more commonly used template filters:

default

If a variable is false or empty, use given default. Otherwise, use the value of the variable. For example:

{{ value|default:"nothing" }}

If value isn't provided or is empty, the above will display "nothing".

length

Returns the length of the value. This works for both strings and lists. For example:

{{ value|length }}

If value is ['a', 'b', 'c', 'd'], the output will be 4.

filesizeformat

Formats the value like a "human-readable" file size (i.e. '13 KB', '4.1 MB', '102 bytes', etc.). For example:

{{ value|filesizeformat }}

value が 123456789 のとき、出力は 117.7 MB になります。

Again, these are just a few examples; see the built-in filter reference for the complete list.

You can also create your own custom template filters; see How to create custom template tags and filters.

参考

Django's admin interface can include a complete reference of all template tags and filters available for a given site. See The Django admin documentation generator.

タグ

Tags look like this: {% tag %}. Tags are more complex than variables: Some create text in the output, some control flow by performing loops or logic, and some load external information into the template to be used by later variables.

Some tags require beginning and ending tags (i.e. {% tag %} ... tag contents ... {% endtag %}).

Django ships with about two dozen built-in template tags. You can read all about them in the built-in tag reference. To give you a taste of what's available, here are some of the more commonly used tags:

for

Loop over each item in an array. For example, to display a list of athletes provided in athlete_list:

<ul>
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
{% endfor %}
</ul>
if, elif, and else

Evaluates a variable, and if that variable is "true" the contents of the block are displayed:

{% if athlete_list %}
    Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
    Athletes should be out of the locker room soon!
{% else %}
    No athletes.
{% endif %}

In the above, if athlete_list is not empty, the number of athletes will be displayed by the {{ athlete_list|length }} variable. Otherwise, if athlete_in_locker_room_list is not empty, the message "Athletes should be out..." will be displayed. If both lists are empty, "No athletes." will be displayed.

You can also use filters and various operators in the if tag:

{% if athlete_list|length > 1 %}
   Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
   Athlete: {{ athlete_list.0.name }}
{% endif %}

While the above example works, be aware that most template filters return strings, so mathematical comparisons using filters will generally not work as you expect. length is an exception.

block and extends
Set up template inheritance (see below), a powerful way of cutting down on "boilerplate" in templates.

Again, the above is only a selection of the whole list; see the built-in tag reference for the complete list.

You can also create your own custom template tags; see How to create custom template tags and filters.

参考

Django's admin interface can include a complete reference of all template tags and filters available for a given site. See The Django admin documentation generator.

コメント

To comment-out part of a line in a template, use the comment syntax: {# #}.

For example, this template would render as 'hello':

{# greeting #}hello

A comment can contain any template code, invalid or not. For example:

{# {% if foo %}bar{% else %} #}

This syntax can only be used for single-line comments (no newlines are permitted between the {# and #} delimiters). If you need to comment out a multiline portion of the template, see the comment tag.

テンプレートの継承

Django のテンプレートエンジンの中で最もパワフルな -- ゆえに最も複雑な -- 部分が、テンプレートの継承です。テンプレートを継承すると、ベースとなる "骨組みの" テンプレートにサイトの共通要素を記述し、block を定義することで子テンプレートにオーバーライドさせることができます。

Let's look at template inheritance by starting with an example:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css">
    <title>{% block title %}My amazing site{% endblock %}</title>
</head>

<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
        {% endblock %}
    </div>

    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

This template, which we'll call base.html, defines an HTML skeleton document that you might use for a two-column page. It's the job of "child" templates to fill the empty blocks with content.

この例では、block タグにより、子テンプレートが埋めることができる 3 つのブロックが定義されています。block タグの仕事は、テンプレートのこれらの部分が子テンプレートによりオーバーライドされる可能性があることをテンプレートエンジンに伝えることです。

子テンプレートは以下のようになります:

{% extends "base.html" %}

{% block title %}My amazing blog{% endblock %}

{% block content %}
{% for entry in blog_entries %}
    <h2>{{ entry.title }}</h2>
    <p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}

ここで重要なのは extends タグです。このタグが、このテンプレートが他のテンプレートを "拡張" することをテンプレートエンジンに伝えるのです。テンプレートシステムがこの点プレートを評価する際に、最初に親テンプレートを探しに行きます -- この例では "base.html" です。

この時点で、テンプレートエンジンは base.html 内の block を認識し、子テンプレートのコンテンツと差し替えます。blog_entries の値に応じて、アウトプットは以下のようになります:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css">
    <title>My amazing blog</title>
</head>

<body>
    <div id="sidebar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    </div>

    <div id="content">
        <h2>Entry one</h2>
        <p>This is my first entry.</p>

        <h2>Entry two</h2>
        <p>This is my second entry.</p>
    </div>
</body>
</html>

子テンプレート内で sidebar を定義していないため、親テンプレートの値がそのまま使われていることに留意してください。親テンプレートの {% block %} タグ内のコンテンツは、常にフォールバックとして使用されます。

継承は、必要なだけ段階を経ることができます。継承を使う一般的な方法は、以下の 3 段階のアプローチです:

  • メインのルック・アンド・フィールを保持する base.html を作成します。
  • それぞれの "セクション" に対して、base_セクション名.html テンプレートを作成します。例えば、base_news.htmlbase_sports.html などです。これらはすべて base.html を拡張 (extends) し、セクション固有のスタイルやデザインを定義します。
  • ページのそれぞれのタイプに対して、個別のテンプレートを作成します。たとえばニュース記事やブログエントリーなどです。これらのテンプレートは、適切なセクションの手プレートを拡張 (extends) します。

This approach maximizes code reuse and helps to add items to shared content areas, such as section-wide navigation.

継承を使用する際のコツをいくつか紹介します:

  • テンプレート内で {% extends %} を使用する際は、その点プレート内で一番最初のテンプレートタグとして指定する必要があります。それ以外の場合、継承が正しく動作しません。

  • ベースのテンプレートには {% block %} タグを多く配置するほどよいです。子テンプレートがすべてのブロックを埋める必要がないことを思い出してください。多くのブロック内に適当なデフォルトを記述しておき、必要なものを後で定義し直せばいいのです。フックは多ければ多いほどいいということです。

  • もし同じコンテンツを複数のテンプレート内で記述していたら、そのコンテンツを親テンプレートの {% block %} に移動させるべきかもしれません。

  • 親テンプレートからブロックのコンテンツを取得する必要がある場合、{{ block.super }} が利用できます。親のブロックを完全にオーバーライドせずに、コンテンツを追加したい場合に有用です。{{ block.super }} を使って挿入されたデータは自動的にエスケープされません (next section を参照してください)。これは、必要な場合は親テンプレートですでにエスケープされているからです。

  • By using the same template name as you are inheriting from, {% extends %} can be used to inherit a template at the same time as overriding it. Combined with {{ block.super }}, this can be a powerful way to make small customizations. See Extending an overridden template in the Overriding templates How-to for a full example.

  • テンプレートタグの as シンタックスを使用して {% block %} の外で生成された変数は、ブロックの内部で使用することはできません。例えば、以下のテンプレートは何も表示しません:

    {% translate "Title" as title %}
    {% block content %}{{ title }}{% endblock %}
    
  • 可読性を増すために、{% endblock %} タグにも 名前 を記述できます。例えば:

    {% block content %}
    ...
    {% endblock content %}
    

    大きなテンプレートでは、このテクニックでどの {% block %} が閉じられているのかが分かりやすくなります。

最後に、同じテンプレート内で同じ名前の block タグを複数定義することはできないことに留意してください。この制限は、block タグが "両方向に" 働くのが理由です。block タグは埋めるための穴を提供するだけではなく -- 親テンプレート 内で穴を埋めるコンテンツを定義します。もし同名の block がテンプレート内に 2 つ存在すると、どちらのブロックのコンテンツを使うべきかテンプレートの親が判断できなくなってしまうのです。

HTML の自動エスケープ

テンプレートから HTML を生成する時には、変数内の文字が HTML のレンダリング結果に悪影響を与えるというリスクが常に付きまといます。例えば、テンプレートに以下のような箇所がある場合を考えてみましょう:

Hello, {{ name }}

一見、このコードはユーザの名前を表示するだけの無害なものと思えます。しかし次のような値が名前として入力されていれば、何が起きるでしょうか:

<script>alert('hello')</script>

この値によって、テンプレートは次のように出力されます:

Hello, <script>alert('hello')</script>

……結果として、ブラウザに JavaScript の警告ボックスをポップアップさせることができてしまいます!

同様に、名前に '<' 文字が含まれていたらどうでしょうか:

<b>username

この値によって、テンプレートはこのように出力されます:

Hello, <b>username

...which, in turn, would result in the remainder of the web page being bolded!

Clearly, user-submitted data shouldn't be trusted blindly and inserted directly into your web pages, because a malicious user could use this kind of hole to do potentially bad things. This type of security exploit is called a Cross Site Scripting (XSS) attack.

この問題を防ぐために、二つの方法があります:

  • 一つは、信頼できない変数は必ず escape フィルタ (後で述べます) に通すことです。このフィルタは危害を及ぼす可能性をもつ HTML 文字を無害な文字に変換します。 この方法は初期の数年間において Django のデフォルトとして採用されていました。しかしユーザー、すなわち開発者やテンプレートの作者にとっては、すべてのデータをエスケープすることを忘れぬよう注意しなければならないという負担になるのが問題です。
  • もう一つは、 Django の自動 HTML エスケープを使うというものです。この節の後半では自動エスケープの仕組みについて述べます。

デフォルトでは、Django はすべてのテンプレートの変数タグの出力を自動的にエスケープするよう設定されています。具体的には、以下の 5 つの文字がエスケープされます:

  • <&lt; に変換
  • >&gt; に変換
  • ' (single quote) is converted to &#x27;
  • " ( ダブルクォート ) を &quot; に変換
  • &&amp; に変換

この動作は、デフォルトで適用されていることを重ねて強調しておきます。Django テンプレートシステムを使っているかぎり、あなたはエスケープに関する問題からは守られているのです。

自動エスケープをオフにする

サイト単位やテンプレート単位、あるいは変数単位でデータの自動エスケープ機能を無効にしたい場合には、いくつかの方法があります。

どんなときに、自動エスケープをオフにする必要があるでしょうか。テンプレート変数の中身は、生の HTML として出力するように意図されたデータかもしれません。そうした場合にはコンテンツがエスケープされてほしくはないでしょう。例えば、データベースに HTML を保存していてテンプレートに直接埋め込みたい場合を考えてみましょう。また、 Django のテンプレートシステムを使って、 HTML 以外 のデータ、例えば電子メールメッセージなどを生成したい場合もあるでしょう。

変数単位での制御

変数単位で個々に自動エスケープを無効にするには、 safe フィルタを使います:

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

safe という言葉は、これ以上エスケープしないよう保護(safe)するとか、 HTML として解釈しても安全(safe)であるという意味だと考えてください。 例えば、 data'<b>' が入っていた場合、出力は以下のようになります:

This will be escaped: &lt;b&gt;
This will not be escaped: <b>

テンプレートブロック単位での制御

To control auto-escaping for a template, wrap the template (or a particular section of the template) in the autoescape tag, like so:

{% autoescape off %}
    Hello {{ name }}
{% endautoescape %}

autoescape タグは、 on または off を引数にとります。 テンプレートのある範囲を自動エスケープし、さらにその一部で自動エスケープをオフにしたい場合には、次のようにできます:

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
    This will not be auto-escaped: {{ data }}.

    Nor this: {{ other_data }}
    {% autoescape on %}
        Auto-escaping applies again: {{ name }}
    {% endautoescape %}
{% endautoescape %}

自動エスケープのタグは、他のブロックタグと同様、タグを設定したテンプレートを継承している他のテンプレートや、 include で取り込んだテンプレートでも有効です。例えば:

base.html
{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}
child.html
{% extends "base.html" %}
{% block title %}This &amp; that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}

ベースのテンプレートで自動エスケープが無効化されているので、子テンプレートでも自動エスケープは無効化されます。結果として、 greeting 変数の値が <b>Hello!</b> のとき、以下の HTML が出力されます:

<h1>This &amp; that</h1>
<b>Hello!</b>

Notes

一般に、テンプレートの作者は自動エスケープをあまり意識する必要はありません。 データをエスケープすべきではない場合を考えたり、データを適切にマークし、テンプレート上でうまく表示されるように考慮するのは、Python 側の開発者 (ビューやカスタムフィルタの開発者)であるべきです。

もしあなたが作成しているテンプレートがどういった状況で使われるのか分からず、自動エスケープが有効かどうかはっきりしない場合には、エスケープの必要な変数全てに escape フィルタを追加してください。自動エスケープがオンの場合、 escape フィルタがデータ を二重にエスケープするような危険性はありません。 escape フィルタは自動エスケープされた変数には影響しなません。

文字列リテラルと自動エスケープ

先に説明したように、フィルタの引数は文字列であってもかまいません:

{{ data|default:"This is a string literal." }}

文字列リテラルは、すべて自動エスケープ**されずに**テンプレート内に挿入され、 safe フィルタを通して渡されたかのように振る舞います。なぜならば、テンプレートの作者はその文字列リテラルに何が書かれているかは把握していますし、テンプレートが書かれる時点でテキストが正しくエスケープされていることは確認できるからです。

したがって、以下のようにテンプレートを書いてください:

{{ data|default:"3 &lt; 2" }}

以下のようにはしないでください:

{{ data|default:"3 < 2" }}  {# Bad! Don't do this. #}

この事が、変数自身に由来するデータに対して何かを引き起こす恐れはありません。 変数の内容はテンプレート作者の管理外にあり、必要に応じて自動的にエスケープされます。

メソッドへのアクセス

オブジェクトに備わったほとんどのメソッドは、テンプレートの中からでも呼び出すことができます。これはテンプレートからアクセスできる対象は、単にクラスの属性 (フィールド名のように) やビューを通した変数だけにはとどまらないということを意味します。例えば Django ORM は Foreign キーに関係するオブジェクトの集合を見つけるために "entry_set” という構文を提供しています。これによって、例えば “comment” と呼ばれるモデルが Foreign キーで ”task” というモデルに関連づけられている場合、テンプレートは task モデルに添えられた全ての comment に対して以下のようにアクセスできます:

{% for comment in task.comment_set.all %}
    {{ comment }}
{% endfor %}

同じように、 QuerySets は、そこに含まれているオブジェクトの個数を数えるため count() というメソッドを提供しています。これによって、 task と関連づけられた全てのコメントの数を取得することも出来ます:

{{ task.comment_set.all.count }}

You can also access methods you've explicitly defined on your own models:

models.py
class Task(models.Model):
    def foo(self):
        return "bar"
template.html
{{ task.foo }}

Django ではテンプレート内でのプログラム的な処理を意図的に制限しているため、テンプレートからメソッドに引数を渡すことはできません。データはビューの中で計算され、テンプレートへは表示のためだけに渡されるべきだからです。

カスタムタグとカスタムフィルタのライブラリ

アプリケーションによっては、カスタムのタグやフィルタライブラリを提供しています。これらをテンプレートで使いたい場合、そのアプリケーションが INSTALLED_APPS に追加されていることを確認し (以下の例では 'django.contrib.humanize' が追加されているものとします) 、そしてテンプレート側で load タグを使います:

{% load humanize %}

{{ 45000|intcomma }}

この例では、 load タグは humanize という名前のタグライブラリを読み込み、 intcomma フィルタを使えるようにしています。 django.contrib.admindocs が有効にされている場合、あなたの admin は現在インストールされているアプリケーションのドキュメント文字列を参照してカスタムライブラリの一覧を得ることができます。

load タグは複数のライブラリ名を同時に読み込めます。ライブラリ名は スペースで区切って下さい:

{% load humanize i18n %}

カスタムのテンプレートライブラリを作成する方法については、 How to create custom template tags and filters を参照してください。

カスタムライブラリとテンプレートの継承

カスタムタグやフィルタライブラリをロードした場合、タグやフィルタは現在のテンプレートだけで利用でき、テンプレート継承パスにおける親テンプレートや子テンプレートでは利用できません。

例えば foo.html{% load humanize %} というタグが入っていても、子テンプレート ( {% extends "foo.html" %} を使っているテンプレート) で humanize という名前のテンプレートタグやフィルタを使えるわけではありません。子テンプレート側で対応するには独自に {% load humanize %} を入れる必要があります。

これはメンテナンス性と健全性を高めるための仕様です。

参考

The Templates Reference
Covers built-in tags, built-in filters, using an alternative template language, and more.