テンプレートデザイナーのドキュメント—Jinjaのドキュメント
テンプレートデザイナーのドキュメント
このドキュメントでは、テンプレートエンジンの構文とセマンティクスについて説明し、Jinjaテンプレートを作成する際のリファレンスとして最も役立ちます。 テンプレートエンジンは非常に柔軟性があるため、アプリケーションからの構成は、区切り文字と未定義の値の動作の点で、ここに示されているコードとわずかに異なる場合があります。
あらすじ
Jinjaテンプレートは単なるテキストファイルです。 Jinjaは、任意のテキストベースの形式(HTML、XML、CSV、LaTeXなど)を生成できます。 Jinjaテンプレートには、特定の拡張子を付ける必要はありません。.html
、.xml
、またはその他の拡張子で十分です。
テンプレートには変数および/または式が含まれ、テンプレートがレンダリングされると値に置き換えられます。 およびタグは、テンプレートのロジックを制御します。 テンプレートの構文は、DjangoとPythonに大きく影響を受けています。
以下は、デフォルトのJinja構成を使用したいくつかの基本を示す最小限のテンプレートです。 詳細については、このドキュメントの後半で説明します。
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
{# a comment #}
</body>
</html>
次の例は、デフォルトの構成設定を示しています。 アプリケーション開発者は、構文構成を{% foo %}
から<% foo %>
などに変更できます。
区切り文字にはいくつかの種類があります。 デフォルトのJinja区切り文字は、次のように構成されています。
- ステートメントの
{% ... %}
テンプレート:...
for Expressions は、テンプレート出力に出力します- コメントの
{# ... #}
はテンプレート出力に含まれていません
行ステートメントとコメントも可能ですが、デフォルトのプレフィックス文字はありません。 それらを使用するには、環境を作成するときにline_statement_prefix
とline_comment_prefix
を設定します。
テンプレートファイル拡張子
上記のように、ファイル拡張子に関係なく、任意のファイルをテンプレートとしてロードできます。 user.html.jinja
のような.jinja
拡張機能を追加すると、一部のIDEまたはエディタープラグインで簡単になる場合がありますが、必須ではありません。 後で紹介する自動エスケープは、ファイル拡張子に基づいて適用できるため、その場合は追加のサフィックスを考慮する必要があります。
テンプレートを識別するためのもう1つの優れたヒューリスティックは、拡張子に関係なく、テンプレートがtemplates
フォルダーにあることです。 これはプロジェクトの一般的なレイアウトです。
変数
テンプレート変数は、テンプレートに渡されるコンテキストディクショナリによって定義されます。
アプリケーションから渡された場合、テンプレート内の変数をいじることができます。 変数には、アクセスできる属性または要素が含まれている場合があります。 変数が持つ属性は、その変数を提供するアプリケーションに大きく依存します。
標準のPython __getitem__
「添え字」構文([]
)に加えて、ドット(.
)を使用して変数の属性にアクセスできます。
次の行は同じことをします:
{{ foo.bar }}
{{ foo['bar'] }}
外側の中括弧は変数のではなく部分であり、printステートメントであることを知っておくことが重要です。 タグ内の変数にアクセスする場合は、それらを中括弧で囲まないでください。
変数または属性が存在しない場合は、未定義の値が返されます。 この種の値で何ができるかは、アプリケーションの構成によって異なります。デフォルトの動作では、印刷または繰り返し実行された場合は空の文字列と評価され、他のすべての操作では失敗します。
実装
便宜上、Jinjaのfoo.bar
はPythonレイヤーで次のことを行います。
- foo (
getattr(foo, 'bar')
)で bar という属性を確認してください - ない場合は、 foo (
foo.__getitem__('bar')
)でアイテム'bar'
を確認します。 - 存在しない場合は、未定義のオブジェクトを返します。
foo['bar']
はほとんど同じように機能しますが、順序が少し異なります。
- foo のアイテム
'bar'
を確認してください。 (foo.__getitem__('bar')
) - 存在しない場合は、 foo の bar という属性を確認してください。 (
getattr(foo, 'bar')
) - 存在しない場合は、未定義のオブジェクトを返します。
これは、オブジェクトに同じ名前のアイテムと属性がある場合に重要です。 さらに、attr()
フィルターは属性のみを検索します。
フィルタ
変数はフィルターで変更できます。 フィルタは、パイプ記号(|
)によって変数から分離され、括弧内にオプションの引数を含めることができます。 複数のフィルターを連鎖させることができます。 1つのフィルターの出力が次のフィルターに適用されます。
たとえば、テンプレート:Name
は、変数 name からすべてのHTMLタグを削除し、出力のタイトルを大文字にします(title(striptags(name))
)。
引数を受け入れるフィルターには、関数呼び出しと同様に、引数を括弧で囲みます。 例:テンプレート:Listx
は、コンマ(str.join(', ', listx)
)でリストを結合します。
以下の組み込みフィルターのリストは、すべての組み込みフィルターについて説明しています。
テスト
フィルタのほかに、いわゆる「テスト」も利用できます。 テストは、一般的な式に対して変数をテストするために使用できます。 変数または式をテストするには、 is と変数の後にテストの名前を追加します。 たとえば、変数が定義されているかどうかを確認するには、name is defined
を実行します。これにより、 name が現在のテンプレートコンテキストで定義されているかどうかに応じてtrueまたはfalseが返されます。
テストも引数を受け入れることができます。 テストで引数が1つしかない場合は、括弧を省略できます。 たとえば、次の2つの式は同じことを行います。
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
以下の組み込みテストのリストは、すべての組み込みテストについて説明しています。
ホワイトスペースコントロール
デフォルト構成の場合:
- 後続の単一のニューラインが存在する場合は削除されます
- 他の空白(スペース、タブ、改行など)は変更されずに返されます
アプリケーションがJinjaを trim_blocks に構成する場合、テンプレートタグの後の最初の改行は(PHPのように)自動的に削除されます。 lstrip_blocks オプションを設定して、行の先頭からブロックの先頭までタブとスペースを削除することもできます。 (ブロックの開始前に他の文字がある場合、何も削除されません。)
trim_blocks と lstrip_blocks の両方を有効にすると、ブロックタグをそれぞれの行に配置でき、レンダリング時にブロック行全体が削除され、コンテンツの空白が保持されます。 たとえば、 trim_blocks および lstrip_blocks オプションがない場合、このテンプレートは次のようになります。
<div>
{% if True %}
yay
{% endif %}
</div>
div内の空白行でレンダリングされます:
<div>
yay
</div>
ただし、 trim_blocks と lstrip_blocks の両方を有効にすると、テンプレートのブロック行が削除され、他の空白が保持されます。
<div>
yay
</div>
ブロックの先頭にプラス記号(+
)を付けることにより、 lstrip_blocks の動作を手動で無効にすることができます。
<div>
{%+ if something %}yay{% endif %}
</div>
同様に、ブロックの最後にプラス記号(+
)を付けることにより、trim_blocks
の動作を手動で無効にすることができます。
<div>
{% if something +%}
yay
{% endif %}
</div>
テンプレートの空白を手動で削除することもできます。 ブロックの開始または終了にマイナス記号(-
)を追加した場合(例: For タグ)、コメント、または変数式の場合、そのブロックの前後の空白は削除されます。
{% for item in seq -%}
{{ item }}
{%- endfor %}
これにより、間に空白のないすべての要素が生成されます。 seq が1
から9
までの数値のリストである場合、出力は123456789
になります。
行ステートメントが有効になっている場合、行の先頭まで先頭の空白が自動的に削除されます。
デフォルトでは、Jinjaは末尾の改行も削除します。 末尾の改行を1つ保持するには、Jinjaを keep_trailing_newline に構成します。
ノート
タグとマイナス記号の間に空白を追加しないでください。
有効:
{%- if foo -%}...{% endif %}
無効:
{% - if foo - %}...{% endif %}
脱出
Jinjaに、変数またはブロックとして処理する部分を無視させることが望ましい場合があります(必要な場合もあります)。 たとえば、デフォルトの構文で、{{
をテンプレートの生の文字列として使用し、変数を開始しない場合は、トリックを使用する必要があります。
リテラル変数区切り文字({{
)を出力する最も簡単な方法は、変数式を使用することです。
{{ '{{' }}
より大きなセクションの場合、ブロック raw をマークすることは理にかなっています。 たとえば、Jinja構文の例をテンプレートに含めるには、次のスニペットを使用できます。
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
ノート
{% raw -%}
タグの最後にあるマイナス記号は、生データの最初の文字の前にあるすべてのスペースと改行を消去します。
行ステートメント
アプリケーションによって行ステートメントが有効になっている場合、行をステートメントとしてマークすることができます。 たとえば、ラインステートメントプレフィックスが#
に設定されている場合、次の2つの例は同等です。
<ul>
# for item in seq
<li>{{ item }}</li>
# endfor
</ul>
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
行ステートメントのプレフィックスは、前にテキストがない限り、行のどこにでも表示できます。 読みやすくするために、ブロックを開始するステートメント( for 、 if 、 elif など)はコロンで終了する場合があります。
# for item in seq:
...
# endfor
ノート
開き括弧、中括弧、または角かっこがある場合、行ステートメントは複数の行にまたがることができます。
<ul>
# for href, caption in [('index.html', 'Index'),
('about.html', 'About')]:
<li><a href="{{ href }}">{{ caption }}</a></li>
# endfor
</ul>
Jinja 2.2以降、行ベースのコメントも利用できます。 たとえば、行コメントプレフィックスが##
に設定されている場合、##
から行末までのすべてが無視されます(改行記号を除く)。
# for item in seq:
<li>{{ item }}</li> ## this comment is ignored
# endfor
テンプレートの継承
Jinjaの最も強力な部分は、テンプレートの継承です。 テンプレートの継承により、サイトのすべての一般的な要素を含み、子テンプレートがオーバーライドできるブロックを定義する基本の「スケルトン」テンプレートを構築できます。
複雑に聞こえますが、非常に基本的です。 例から始めることでそれを理解するのが最も簡単です。
基本テンプレート
このテンプレート(base.html
と呼びます)は、単純な2列のページに使用できる単純なHTMLスケルトンドキュメントを定義します。 空のブロックをコンテンツで埋めるのは「子」テンプレートの仕事です。
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
この例では、{% block %}
タグは、子テンプレートが入力できる4つのブロックを定義します。 block タグが行うのは、子テンプレートがテンプレート内のそれらのプレースホルダーをオーバーライドする可能性があることをテンプレートエンジンに通知することだけです。
block
タグは、if
などの他のブロック内に配置できますが、if
ブロックが実際にレンダリングされているかどうかに関係なく、常に実行されます。
子テンプレート
子テンプレートは次のようになります。
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
ここで重要なのは{% extends %}
タグです。 これは、このテンプレートが別のテンプレートを「拡張」することをテンプレートエンジンに通知します。 テンプレートシステムがこのテンプレートを評価するとき、最初に親を見つけます。 extendsタグは、テンプレートの最初のタグである必要があります。 それが正常に印刷される前のすべては、混乱を引き起こす可能性があります。 この動作とその利用方法の詳細については、 Null-Default Fallback を参照してください。 また、周囲の条件が真であるか偽であるかに関わらず、ブロックは常に埋められます。
テンプレートのファイル名は、テンプレートローダーによって異なります。 たとえば、 FileSystemLoader を使用すると、ファイル名を指定して他のテンプレートにアクセスできます。 スラッシュを使用してサブディレクトリのテンプレートにアクセスできます。
{% extends "layout/default.html" %}
ただし、この動作は、Jinjaを埋め込んだアプリケーションに依存する可能性があります。 子テンプレートはfooter
ブロックを定義しないため、代わりに親テンプレートの値が使用されることに注意してください。
同じテンプレートに同じ名前の複数の{% block %}
タグを定義することはできません。 この制限が存在するのは、ブロックタグが「両」方向で機能するためです。 つまり、ブロックタグは、入力するプレースホルダーを提供するだけでなく、親のプレースホルダーを入力するコンテンツも定義します。 テンプレートに同じ名前の{% block %}
タグが2つある場合、そのテンプレートの親は、ブロックのコンテンツのどちらを使用するかを知りません。
ただし、ブロックを複数回印刷する場合は、特別な self 変数を使用して、その名前でブロックを呼び出すことができます。
<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
スーパーブロック
super()
を呼び出すことにより、親ブロックの内容をレンダリングすることができます。 これにより、親ブロックの結果が返されます。
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ super() }}
{% endblock %}
ネスティングが拡張されます
{% extends %}
の複数のレベルの場合、super
参照をチェーンして(super.super()
のように)、継承ツリーのレベルをスキップできます。
例えば:
# parent.tmpl
body: {% block body %}Hi from parent.{% endblock %}
# child.tmpl
{% extends "parent.tmpl" %}
{% block body %}Hi from child. {{ super() }}{% endblock %}
# grandchild1.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild1.{% endblock %}
# grandchild2.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild2. {{ super.super() }} {% endblock %}
child.tmpl
をレンダリングすると、body: Hi from child. Hi from parent.
が得られます。
grandchild1.tmpl
をレンダリングすると、body: Hi from grandchild1.
が得られます。
grandchild2.tmpl
をレンダリングすると、body: Hi from grandchild2. Hi from parent.
が得られます。
ブロックの入れ子とスコープ
ブロックをネストして、より複雑なレイアウトにすることができます。 ただし、デフォルトでは、ブロックは外部スコープから変数にアクセスできない場合があります。
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
この例では、 item がブロック内で使用できないため、空の<li>
アイテムが出力されます。 これは、ブロックが子テンプレートに置き換えられた場合、ブロックで定義されていない、またはコンテキストに渡されていない変数が表示されるためです。
Jinja 2.2以降では、ブロック宣言に scoped 修飾子を追加してブロックを「スコープ」に設定することにより、変数がブロックで使用可能であることを明示的に指定できます。
{% for item in seq %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}
ブロックをオーバーライドする場合、 scoped 修飾子を指定する必要はありません。
必要なブロック
ブロックはrequired
としてマークできます。 それらはある時点でオーバーライドする必要がありますが、必ずしも直接の子テンプレートによってオーバーライドされるとは限りません。 必要なブロックにはスペースとコメントのみを含めることができ、直接レンダリングすることはできません。
{% block body required %}{% endblock %}
{% extends "page.txt" %}
{% extends "issue.txt" %}
{% block body %}Provide steps to demonstrate the bug.{% endblock %}
page.txt
またはissue.txt
をレンダリングすると、body
ブロックがオーバーライドされないため、TemplateRuntimeError
が発生します。 bug_report.txt
のレンダリングは、ブロックをオーバーライドするため成功します。
scoped
と組み合わせる場合、required
修飾子は、スコープ修飾子のの後に配置する必要があります。 いくつかの有効な例を次に示します。
{% block body scoped %}{% endblock %}
{% block body required %}{% endblock %}
{% block body scoped required %}{% endblock %}
テンプレートオブジェクト
バージョン2.4で変更されました。
テンプレートオブジェクトがテンプレートコンテキストで渡された場合は、そのオブジェクトから拡張することもできます。 呼び出し元のコードがレイアウトテンプレートを layout_template として環境に渡すと仮定すると、このコードは次のように機能します。
{% extends layout_template %}
以前は、 layout_template 変数は、これが機能するためにレイアウトテンプレートのファイル名を含む文字列である必要がありました。
HTMLエスケープ
テンプレートからHTMLを生成する場合、結果のHTMLに影響を与える文字が変数に含まれるリスクが常にあります。 2つのアプローチがあります:
- 各変数を手動でエスケープします。 また
- デフォルトではすべてを自動的にエスケープします。
Jinjaは両方をサポートしています。 使用されるものは、アプリケーションの構成によって異なります。 デフォルトの構成は自動エスケープなしです。 さまざまな理由で:
- 安全な値を除いてすべてをエスケープするということは、JinjaがHTMLを含まないことがわかっている変数をエスケープしていることも意味します(例: 数値、ブール値)これはパフォーマンスに大きな打撃を与える可能性があります。
- 変数の安全性に関する情報は非常に壊れやすいものです。 安全な値と安全でない値を強制変換することにより、戻り値が二重エスケープされたHTMLになる可能性があります。
手動エスケープの操作
手動エスケープが有効になっている場合、必要に応じて変数をエスケープするのはあなたのの責任です。 何を逃れる? may に次の文字(>
、<
、&
、または"
)のいずれかが含まれる変数がある場合 SHOULD は、変数に整形式で信頼できるHTMLが含まれていない限り、エスケープする必要があります。 エスケープは、変数を|e
フィルターにパイプすることで機能します。
{{ user.username|e }}
自動エスケープの操作
自動エスケープが有効になっている場合、安全として明示的にマークされた値を除いて、デフォルトですべてがエスケープされます。 変数と式は、次のいずれかで安全としてマークできます。
markupsafe.Markup
を使用したアプリケーションによるコンテキスト辞書|safe
フィルターを備えたテンプレート。
安全とマークした文字列が、そのマークを理解しない他のPythonコードを通過すると、失われる可能性があります。 テンプレートに到達する前に、データが安全であるとマークされたときと、データがどのように処理されるかに注意してください。
値がエスケープされているが安全とマークされていない場合でも、自動エスケープが実行され、二重エスケープ文字が生成されます。 すでに安全であるがマークされていないデータがあることがわかっている場合は、必ずMarkup
でラップするか、|safe
フィルターを使用してください。
Jinja関数(マクロ、 super 、 self.BLOCKNAME )は、常に安全とマークされたテンプレートデータを返します。
自動エスケープ機能を備えたテンプレートの文字列リテラルは、ネイティブPython文字列が安全ではないため、安全でないと見なされます。
制御構造のリスト
制御構造とは、プログラムのフローを制御するすべてのものを指します-条件付き(つまり、 if / elif / else)、forループ、およびマクロやブロックなど。 デフォルトの構文では、制御構造は{% ... %}
ブロック内に表示されます。
にとって
シーケンス内の各アイテムをループします。 たとえば、 users という変数で提供されるユーザーのリストを表示するには次のようにします。
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
テンプレート内の変数はオブジェクトプロパティを保持するため、 dict のようなコンテナを反復処理することができます。
<dl>
{% for key, value in my_dict.items() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
Python dictは、表示したい順序になっていない可能性があります。 順序が重要な場合は、|dictsort
フィルターを使用してください。
<dl>
{% for key, value in my_dict | dictsort %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
forループブロック内で、いくつかの特別な変数にアクセスできます。
変数 | 説明 |
---|---|
loop.index | ループの現在の反復。 (1つのインデックス付き) |
loop.index0 | ループの現在の反復。 (0インデックス付き) |
loop.revindex | ループの終わりからの反復回数(1つのインデックス付き) |
loop.revindex0 | ループの終わりからの反復回数(0インデックス付き) |
loop.first | 最初の反復の場合は真。 |
loop.last | 最後の反復の場合はTrue。 |
loop.length | シーケンス内のアイテムの数。 |
loop.cycle | シーケンスのリスト間を循環するヘルパー関数。 以下の説明を参照してください。 |
loop.depth | 再帰ループの現在のレンダリングの深さを示します。 レベル1から開始 |
loop.depth0 | 再帰ループの現在のレンダリングの深さを示します。 レベル0から開始 |
loop.previtem | ループの前の反復からのアイテム。 最初の反復では未定義。 |
loop.nextitem | ループの次の反復からのアイテム。 最後の反復では未定義です。 |
loop.changed(* val) | 以前に別の値で呼び出された(またはまったく呼び出されなかった)場合はTrue。 |
forループ内では、特別な loop.cycle ヘルパーを使用して、ループを通過するたびに文字列/変数のリスト間を循環することができます。
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
Jinja 2.1以降、ループアンバウンドサイクリングを可能にする追加の cycle ヘルパーが存在します。 詳細については、グローバル関数のリストを参照してください。
Pythonとは異なり、ループ内でブレークまたは続行することはできません。 ただし、反復中にシーケンスをフィルタリングできるため、アイテムをスキップできます。 次の例では、非表示になっているすべてのユーザーをスキップします。
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
利点は、特別な loop 変数が正しくカウントされることです。 したがって、繰り返されていないユーザーはカウントされません。
シーケンスが空であるか、フィルタリングによってシーケンスからすべてのアイテムが削除されたために反復が行われなかった場合は、 else を使用してデフォルトのブロックをレンダリングできます。
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>
Pythonでは、対応するループが break を実行しなかった場合は常に、 else ブロックが実行されることに注意してください。 Jinjaループはとにかく break できないため、 else キーワードのわずかに異なる動作が選択されました。
ループを再帰的に使用することも可能です。 これは、サイトマップやRDFaなどの再帰データを処理する場合に役立ちます。 ループを再帰的に使用するには、基本的に recursive 修飾子をループ定義に追加し、再帰する場所で新しいiterableを使用して loop 変数を呼び出す必要があります。
次の例では、再帰ループを使用してサイトマップを実装します。
<ul class="sitemap">
{%- for item in sitemap recursive %}
<li><a href="{{ item.href|e }}">{{ item.title }}</a>
{%- if item.children -%}
<ul class="submenu">{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
loop 変数は、常に最も近い(最も内側の)ループを参照します。 ループのレベルが複数ある場合は、再帰的に使用するループの後に {%set outside_loop = loop%} と書き込むことで、変数 loop を再バインドできます。 次に、 テンプレート:Outer loop(…) を使用して呼び出すことができます。
ループ内の割り当ては反復の終了時にクリアされ、ループスコープを超えることはできないことに注意してください。 古いバージョンのJinjaにはバグがあり、状況によっては割り当てが機能するように見えました。 これはサポートされていません。 これに対処する方法の詳細については、割り当てを参照してください。
前回の反復以降に値が変更されたかどうか、または次の反復で変更されるかどうかを確認するだけの場合は、 previtem および nextitem を使用できます。
{% for value in values %}
{% if loop.previtem is defined and value > loop.previtem %}
The value just increased!
{% endif %}
{{ value }}
{% if loop.nextitem is defined and loop.nextitem > value %}
The value will increase even more!
{% endif %}
{% endfor %}
値がまったく変更されたかどうかだけを気にする場合は、 changed を使用する方がさらに簡単です。
{% for entry in entries %}
{% if loop.changed(entry.category) %}
<h2>{{ entry.category }}</h2>
{% endif %}
<p>{{ entry.message }}</p>
{% endfor %}
もしも
Jinjaの if ステートメントは、Pythonのifステートメントに相当します。 最も単純な形式では、これを使用して、変数が定義されているかどうか、空ではないか、falseではないかをテストできます。
{% if users %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
複数のブランチの場合、Pythonのように elif と else を使用できます。 そこでは、より複雑な Expressions を使用することもできます。
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
インライン式およびループフィルタリングとしても使用できる場合。
マクロ
マクロは、通常のプログラミング言語の関数に匹敵します。 これらは、頻繁に使用されるイディオムを再利用可能な関数に入れて、繰り返さないようにするのに役立ちます(「DRY」)。
フォーム要素をレンダリングするマクロの小さな例を次に示します。
{% macro input(name, value='', type='text', size=20) -%}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}" size="{{ size }}">
{%- endmacro %}
マクロは、名前空間内の関数のように呼び出すことができます。
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
マクロが別のテンプレートで定義されている場合は、最初にインポートする必要があります。
マクロ内では、次の3つの特別な変数にアクセスできます。
- varargs
- マクロで受け入れられるよりも多くの位置引数がマクロに渡されると、それらは値のリストとして特別な varargs 変数に入れられます。
- kwargs
- varargs と似ていますが、キーワード引数用です。 消費されていないすべてのキーワード引数は、この特別な変数に格納されます。
- 発信者
- マクロが call タグから呼び出された場合、呼び出し元は呼び出し可能マクロとしてこの変数に格納されます。
マクロは、内部の詳細の一部も公開します。 マクロオブジェクトでは、次の属性を使用できます。
- 名前
- マクロの名前。
テンプレート:Input.name
はinput
を印刷します。 - 引数
- マクロが受け入れる引数の名前のタプル。
- デフォルト
- デフォルト値のタプル。
- catch_kwargs
- マクロが追加のキーワード引数を受け入れる場合(つまり、特別な kwargs 変数にアクセスする場合)、これは true です。
- catch_varargs
- マクロが追加の位置引数を受け入れる場合(つまり、特別な varargs 変数にアクセスする場合)、これは true です。
- 発信者
- マクロが特別な caller 変数にアクセスし、 call タグから呼び出される可能性がある場合、これは true です。
マクロ名がアンダースコアで始まる場合、そのマクロ名はエクスポートされず、インポートできません。
電話
場合によっては、マクロを別のマクロに渡すと便利なことがあります。 この目的のために、特別な call ブロックを使用できます。 次の例は、呼び出し機能を利用するマクロとその使用方法を示しています。
{% macro render_dialog(title, class='dialog') -%}
<div class="{{ class }}">
<h2>{{ title }}</h2>
<div class="contents">
{{ caller() }}
</div>
</div>
{%- endmacro %}
{% call render_dialog('Hello World') %}
This is a simple dialog rendered by using a macro and
a call block.
{% endcall %}
引数を呼び出しブロックに戻すこともできます。 これにより、ループの代わりとして役立ちます。 一般的に、呼び出しブロックは名前のないマクロとまったく同じように機能します。
呼び出しブロックを引数とともに使用する方法の例を次に示します。
{% macro dump_users(users) -%}
<ul>
{%- for user in users %}
<li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
{%- endfor %}
</ul>
{%- endmacro %}
{% call(user) dump_users(list_of_user) %}
<dl>
<dt>Realname</dt>
<dd>{{ user.realname|e }}</dd>
<dt>Description</dt>
<dd>{{ user.description }}</dd>
</dl>
{% endcall %}
フィルタ
フィルタセクションを使用すると、テンプレートデータのブロックに通常のJinjaフィルタを適用できます。 特別な filter セクションでコードをラップするだけです。
{% filter upper %}
This text becomes uppercase
{% endfilter %}
課題
コードブロック内で、変数に値を割り当てることもできます。 トップレベル(ブロック、マクロ、またはループの外側)の割り当ては、トップレベルのマクロと同様にテンプレートからエクスポートされ、他のテンプレートからインポートできます。
割り当ては set タグを使用し、複数のターゲットを持つことができます。
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}
スコープ動作
ブロック内に変数を設定して、ブロック外に表示させることはできないことに注意してください。 これはループにも当てはまります。 その規則の唯一の例外は、スコープを導入しないifステートメントです。 その結果、次のテンプレートは期待どおりの動作をしません。
{% set iterated = false %}
{% for item in seq %}
{{ item }}
{% set iterated = true %}
{% endfor %}
{% if not iterated %} did not iterate {% endif %}
Jinja構文ではこれを行うことはできません。 代わりに、loopelseブロックや特別な loop 変数などの代替構造を使用してください。
{% for item in seq %}
{{ item }}
{% else %}
did not iterate
{% endfor %}
バージョン2.10以降、スコープ間で変更を伝播できる名前空間オブジェクトを使用して、より複雑なユースケースを処理できます。
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
set タグのobj.attr
表記は、名前空間オブジェクトにのみ許可されていることに注意してください。 他のオブジェクトに属性を割り当てようとすると、例外が発生します。
バージョン2.10の新機能:名前空間オブジェクトのサポートが追加されました
ブロック割り当て
バージョン2.8の新機能。
Jinja 2.8以降では、ブロック割り当てを使用して、ブロックの内容を変数名に取り込むこともできます。 これは、マクロの代わりとして、状況によっては役立つ場合があります。 その場合、等号と値を使用する代わりに、変数名を書き込んでから、{% endset %}
がキャプチャされるまですべてを記述します。
例:
{% set navigation %}
<li><a href="/">Index</a>
<li><a href="/downloads">Downloads</a>
{% endset %}
Navigation 変数には、ナビゲーションHTMLソースが含まれています。
バージョン2.10で変更されました。
Jinja 2.10以降、ブロック割り当てはフィルターをサポートします。
例:
{% set reply | wordwrap %}
You wrote:
{{ message }}
{% endset %}
拡張します
extends タグを使用して、あるテンプレートを別のテンプレートから拡張できます。 1つのファイルに複数の extends タグを含めることができますが、一度に実行できるのはそのうちの1つだけです。
上記のテンプレートの継承に関するセクションを参照してください。
含む
include タグは、テンプレートをインクルードし、そのファイルのレンダリングされたコンテンツを現在の名前空間に返すのに役立ちます。
{% include 'header.html' %}
Body
{% include 'footer.html' %}
含まれているテンプレートは、デフォルトでアクティブなコンテキストの変数にアクセスできます。 インポートとインクルードのコンテキスト動作の詳細については、インポートコンテキスト動作を参照してください。
Jinja 2.2以降では、ignore missing
でインクルードをマークできます。 その場合、含まれるテンプレートが存在しない場合、Jinjaはステートメントを無視します。 with
またはwithout context
と組み合わせる場合は、コンテキスト可視性ステートメントの前に配置する必要があります。 いくつかの有効な例を次に示します。
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
バージョン2.2の新機能。
含める前に存在がチェックされるテンプレートのリストを提供することもできます。 存在する最初のテンプレートが含まれます。 ignoremissing が指定されている場合、テンプレートが存在しない場合は何もレンダリングしないようにフォールバックします。それ以外の場合は例外が発生します。
例:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
バージョン2.4で変更:テンプレートオブジェクトがテンプレートコンテキストに渡された場合、 include を使用してそのオブジェクトを含めることができます。
輸入
Jinjaは、頻繁に使用されるコードをマクロに入れることをサポートしています。 これらのマクロは、さまざまなテンプレートに移動して、そこからインポートできます。 これは、Pythonのimportステートメントと同様に機能します。 インポートはキャッシュされ、インポートされたテンプレートは現在のテンプレート変数にアクセスできず、デフォルトではグローバルのみにアクセスできることを知っておくことが重要です。 インポートとインクルードのコンテキスト動作の詳細については、インポートコンテキスト動作を参照してください。
テンプレートをインポートする方法は2つあります。 完全なテンプレートを変数にインポートするか、特定のマクロ/エクスポートされた変数を変数から要求できます。
フォームをレンダリングするヘルパーモジュール( forms.html と呼ばれる)があると想像してください。
{% macro input(name, value='', type='text') -%}
<input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}
{%- macro textarea(name, value='', rows=10, cols=40) -%}
<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
}}">{{ value|e }}</textarea>
{%- endmacro %}
テンプレートの変数とマクロにアクセスする最も簡単で柔軟な方法は、テンプレートモジュール全体を変数にインポートすることです。 このようにして、属性にアクセスできます。
{% import 'forms.html' as forms %}
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd>
<dt>Password</dt>
<dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>
または、特定の名前をテンプレートから現在の名前空間にインポートすることもできます。
{% from 'forms.html' import input as input_field, textarea %}
<dl>
<dt>Username</dt>
<dd>{{ input_field('username') }}</dd>
<dt>Password</dt>
<dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>
1つ以上の下線で始まるマクロと変数はプライベートであり、インポートできません。
バージョン2.4で変更:テンプレートオブジェクトがテンプレートコンテキストに渡された場合、そのオブジェクトからインポートできます。
コンテキストの動作をインポートする
デフォルトでは、含まれているテンプレートには現在のコンテキストが渡されますが、インポートされたテンプレートには渡されません。 これは、インクルードとは異なり、インポートがキャッシュされるためです。 インポートは、マクロを保持するモジュールとして使用されることがよくあります。
この動作は明示的に変更できます。import/ includeディレクティブに with context または without context を追加すると、現在のコンテキストをテンプレートに渡すことができ、キャッシュが自動的に無効になります。
次に2つの例を示します。
{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}
ノート
Jinja 2.0では、含まれているテンプレートに渡されたコンテキストに、テンプレートで定義されている変数が含まれていませんでした。 実際のところ、これは機能しませんでした。
{% for box in boxes %}
{% include "render_box.html" %}
{% endfor %}
含まれているテンプレートrender_box.html
は、Jinja2.0のボックスにアクセスできません。 Jinja 2.1の時点で、render_box.html
はで実行できます。
式
Jinjaはどこでも基本的な表現を可能にします。 これらは通常のPythonと非常によく似ています。 Pythonを使用していない場合でも、Pythonに慣れているはずです。
リテラル
式の最も単純な形式はリテラルです。 リテラルは、文字列や数値などのPythonオブジェクトの表現です。 次のリテラルが存在します。
"Hello World"
2つの二重引用符または一重引用符の間はすべて文字列です。 テンプレートに文字列が必要な場合に役立ちます(例: 関数呼び出しとフィルターへの引数として、または単にテンプレートを拡張または含めるため)。
42
/123_456
整数は、小数部のない整数です。 '_'文字は、読みやすくするためにグループを区切るために使用できます。
42.23
/42.1e2
/123_456.789
浮動小数点数は「。」を使用して書き込むことができます。 小数点として。 また、指数部分を示すために大文字または小文字の「e」を使用して科学的記数法で記述することもできます。 '_'文字は、読みやすさのためにグループを区切るために使用できますが、指数部分では使用できません。
['list', 'of', 'objects']
2つの括弧の間はすべてリストです。 リストは、繰り返される順次データを格納するのに役立ちます。 たとえば、forループのリストとタプルを使用して(およびforループを使用して)リンクのリストを簡単に作成できます。
<ul> {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), ('downloads.html', 'Downloads')] %} <li><a href="{{ href }}">{{ caption }}</a></li> {% endfor %} </ul>
('tuple', 'of', 'values')
タプルは、変更できない(「不変」)リストのようなものです。 タプルに項目が1つしかない場合は、その後にコンマ(
('1-tuple',)
)を付ける必要があります。 タプルは通常、2つ以上の要素のアイテムを表すために使用されます。 詳細については、上記のリストの例を参照してください。{'dict': 'of', 'key': 'and', 'value': 'pairs'}
Pythonのdictは、キーと値を組み合わせた構造です。 キーは一意である必要があり、常に1つの値を持っている必要があります。 ディクトがテンプレートで使用されることはめったにありません。
xmlattr()
フィルターなどのまれなケースで役立ちます。true
/false
true
は常に真であり、false
は常に偽です。
ノート
特別な定数 true 、 false 、および none は確かに小文字です。 これは過去に混乱を引き起こしたため( True は、falseと見なされた未定義の変数に展開されていました)、3つすべてをタイトルケースで記述できるようになりました( True 、[X190X ] False 、および None )。 ただし、一貫性を保つために(すべてのJinja識別子は小文字です)、小文字のバージョンを使用する必要があります。
算数
Jinjaでは、値を使用して計算できます。 これがテンプレートで役立つことはめったにありませんが、完全を期すために存在します。 次の演算子がサポートされています。
+
- 2つのオブジェクトを一緒に追加します。 通常、オブジェクトは数値ですが、両方が文字列またはリストの場合は、この方法で連結できます。 ただし、これは文字列を連結するための推奨される方法ではありません。 文字列の連結については、
~
演算子を参照してください。テンプレート:1 + 1
は2
です。 -
- 最初の数値から2番目の数値を引きます。
テンプレート:3 - 2
は1
です。 /
- 2つの数を割ります。 戻り値は浮動小数点数になります。
テンプレート:1 / 2
はテンプレート:0.5
です。 //
- 2つの数値を除算し、切り捨てられた整数の結果を返します。
テンプレート:20 // 7
は2
です。 %
- 整数除算の余りを計算します。
テンプレート:11 % 7
は4
です。 *
- 左のオペランドに右のオペランドを掛けます。
テンプレート:2 * 2
は4
を返します。 これは、文字列を複数回繰り返すためにも使用できます。テンプレート:'=' * 80
は、80の等号のバーを印刷します。 **
- 左のオペランドを右のオペランドの累乗にします。
テンプレート:2**3
は8
を返します。
比較
==
- 2つのオブジェクトが等しいかどうかを比較します。
!=
- 2つのオブジェクトの不平等を比較します。
>
true
左側が右側よりも大きい場合。>=
true
左側が右側以上の場合。<
true
左側が右側よりも低い場合。<=
true
左側が右側以下の場合。
論理
if
ステートメント、for
フィルタリング、およびif
式の場合、複数の式を組み合わせると便利です。
and
- 左と右のオペランドがtrueの場合、trueを返します。
or
- 左または右のオペランドがtrueの場合、trueを返します。
not
- ステートメントを否定します(以下を参照)。
(expr)
- 括弧は式をグループ化します。
ノート
is
およびin
演算子は、not foo is bar
および [の代わりにfoo is not bar
およびfoo not in bar
という中置記法を使用した否定もサポートします。 X138X]。 他のすべての式にはプレフィックス表記が必要です:not (foo and bar).
その他の演算子
次の演算子は非常に便利ですが、他の2つのカテゴリのいずれにも当てはまりません。
in
シーケンス/マッピング封じ込めテストを実行します。 左のオペランドが右に含まれている場合はtrueを返します。 たとえば、
{{ 1 in [1, 2, 3] }}
はtrueを返します。is
テストを実行します。
|
(パイプ、垂直バー)フィルターを適用します。
~
(チルダ)すべてのオペランドを文字列に変換し、それらを連結します。
テンプレート:"Hello " ~ name ~ "!"
は戻ります( name が'John'
に設定されていると仮定)Hello John!
。()
呼び出し可能オブジェクトを呼び出します:
テンプレート:Post.render()
。 括弧内では、Pythonのように位置引数とキーワード引数を使用できます。.
/[]
オブジェクトの属性を取得します。 (変数を参照)
式の場合
インライン if 式を使用することもできます。 これらはいくつかの状況で役立ちます。 たとえば、これを使用して、変数が定義されている場合は1つのテンプレートから拡張でき、そうでない場合はデフォルトのレイアウトテンプレートから拡張できます。
{% extends layout_template if layout_template is defined else 'default.html' %}
一般的な構文は<do something> if <something is true> else <do something else>
です。
else 部分はオプションです。 指定しない場合、elseブロックは暗黙的に Undefined オブジェクトに評価されます(環境内のundefined
が何に設定されているかに関係なく)。
{{ "[{}]".format(page.title) if page.title }}
Pythonメソッド
変数の型で定義された任意のメソッドを使用することもできます。 メソッド呼び出しから返された値は、式の値として使用されます。 文字列で定義されたメソッドを使用する例を次に示します(page.title
は文字列です)。
{{ page.title.capitalize() }}
これは、ユーザー定義型のメソッドで機能します。 たとえば、タイプFoo
の変数f
にメソッドbar
が定義されている場合、次の操作を実行できます。
{{ f.bar(value) }}
演算子メソッドも期待どおりに機能します。 たとえば、%
は文字列のprintfスタイルを実装します。
{{ "Hello, %s!" % name }}
その場合は.format
メソッドを使用する必要があります(これは、テンプレートのレンダリングのコンテキストで少し工夫されています)。
{{ "Hello, {}!".format(name) }}
組み込みフィルターのリスト
組み込みテストのリスト
グローバル関数のリスト
次の関数は、デフォルトでグローバルスコープで使用できます。
- jinja-globals.range([start, ]stop[, step])
整数の等差数列を含むリストを返します。
range(i, j)
は[i, i+1, i+2, ..., j-1]
を返します。 start(!)のデフォルトは0
です。 stepを指定すると、インクリメント(またはデクリメント)が指定されます。 たとえば、range(4)
とrange(0, 4, 1)
は[0, 1, 2, 3]
を返します。 終点は省略! これらは、4つの要素のリストに対して正確に有効なインデックスです。これは、テンプレートブロックを複数回繰り返す場合に便利です。 リストに記入します。 リストに7人のユーザーがいるが、CSSで高さを強制するために3つの空のアイテムをレンダリングするとします。
<ul> {% for user in users %} <li>{{ user.username }}</li> {% endfor %} {% for number in range(10 - users|count) %} <li class="empty"><span>...</span></li> {% endfor %} </ul>
- jinja-globals.lipsum(n=5, html=True, min=20, max=100)
- テンプレートのloremipsumを生成します。 デフォルトでは、HTMLの5つの段落が生成され、各段落は20〜100語です。 htmlがFalseの場合、通常のテキストが返されます。 これは、レイアウトテスト用の単純なコンテンツを生成するのに役立ちます。
- jinja-globals.dict(\**items)
- dictリテラルの便利な代替手段。
{'foo': 'bar'}
はdict(foo='bar')
と同じです。
- class jinja-globals.cycler(\*items)
一度に1つずつ値を生成して値を循環し、最後に達したら再起動します。
loop.cycle
に似ていますが、ループの外側または複数のループで使用できます。 たとえば、フォルダとファイルのリストをリスト内にレンダリングし、それらに「奇数」クラスと「偶数」クラスを交互に与えます。{% set row_class = cycler("odd", "even") %} <ul class="browser"> {% for folder in folders %} <li class="folder {{ row_class.next() }}">{{ folder }} {% endfor %} {% for file in files %} <li class="file {{ row_class.next() }}">{{ file }} {% endfor %} </ul>
- パラメーター
items –各位置引数は、各サイクルに指定された順序で生成されます。
バージョン2.1の新機能。
- property current
現在のアイテムを返します。 次回 next()が呼び出されたときに返されるアイテムに相当します。
- next()
現在のアイテムを返し、現在を次のアイテムに進めます。
- reset()
現在のアイテムを最初のアイテムにリセットします。
- class jinja-globals.joiner(sep=', ')
複数のセクションを「結合」するために使用できる小さなヘルパー。 ジョイナには文字列が渡され、最初のときを除いて、呼び出されるたびにその文字列が返されます(この場合、空の文字列が返されます)。 これを使用して、物事に参加できます。
{% set pipe = joiner("|") %} {% if categories %} {{ pipe() }} Categories: {{ categories|join(", ") }} {% endif %} {% if author %} {{ pipe() }} Author: {{ author() }} {% endif %} {% if can_edit %} {{ pipe() }} <a href="?action=edit">Edit</a> {% endif %}
バージョン2.1の新機能。
- class jinja-globals.namespace(...)
{% set %}
タグを使用して属性の割り当てを可能にする新しいコンテナを作成します。{% set ns = namespace() %} {% set ns.foo = 'bar' %}
これの主な目的は、ループ本体内から外部スコープに値を運ぶことを可能にすることです。 初期値は、dict、キーワード引数、またはその両方として提供できます(Pythonの dict コンストラクターと同じ動作)。
{% set ns = namespace(found=false) %} {% for item in items %} {% if item.check_something() %} {% set ns.found = true %} {% endif %} * {{ item.title }} {% endfor %} Found item having something: {{ ns.found }}
バージョン2.10の新機能。
拡張機能
次のセクションでは、アプリケーションによって有効になる可能性のある組み込みのJinja拡張機能について説明します。 アプリケーションは、このドキュメントでカバーされていない追加の拡張機能を提供することもできます。 その場合、上記の拡張機能を説明する別のドキュメントが必要です。
i18n
i18n Extension が有効になっている場合、テンプレート内のテキストを翻訳可能としてマークすることができます。 セクションを翻訳可能としてマークするには、trans
ブロックを使用します。
{% trans %}Hello, {{ user }}!{% endtrans %}
ブロック内では、ステートメントは許可されず、テキストと単純な変数タグのみが許可されます。
変数タグは名前のみにすることができ、属性アクセス、フィルター、またはその他の式にすることはできません。 式を使用するには、ブロックで使用するtrans
タグの名前に式をバインドします。
{% trans user=user.username %}Hello, {{ user }}!{% endtrans %}
複数の式をバインドするには、それぞれをコンマ(,
)で区切ります。
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}
複数形にするには、pluralize
タグで区切って単数形と複数形の両方を指定します。
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}
デフォルトでは、ブロックの最初の変数は、単数形と複数形のどちらを使用するかを決定するために使用されます。 それが正しくない場合は、複数化に使用する変数をpluralize
のパラメーターとして指定してください。
{% trans ..., user_count=users|length %}...
{% pluralize user_count %}...{% endtrans %}
テキストのブロックを翻訳する場合、空白と改行は読みにくく、エラーが発生しやすい翻訳文字列になります。 これを回避するために、トランスブロックをトリミングとしてマークすることができます。これにより、すべての改行とそれらを囲む空白が1つのスペースに置き換えられ、先頭と末尾の空白が削除されます。
{% trans trimmed book_title=book.title %}
This is {{ book_title }}.
You should read it!
{% endtrans %}
これにより、翻訳ファイルにThis is %(book_title)s. You should read it!
が作成されます。
トリミングがグローバルに有効になっている場合は、notrimmed
修飾子を使用してブロックに対してトリミングを無効にすることができます。
バージョン2.10の新機能: trimmed
およびnotrimmed
修飾子が追加されました。
これらの関数を使用して、式の文字列を変換することができます。
gettext
:単一の文字列を翻訳しますngettext
:複数形の文字列を翻訳します_
:gettext
のエイリアス
次のように翻訳された文字列を印刷できます。
{{ _("Hello, World!") }}
プレースホルダーを使用するには、format
フィルターを使用します。
{{ _("Hello, %(user)s!")|format(user=user.username) }}
他の言語では同じ順序で単語を使用できない場合があるため、format
には常にキーワード引数を使用してください。
New Style Gettext 呼び出しがアクティブになっている場合、プレースホルダーの使用が簡単になります。 書式設定は、format
フィルターを使用する代わりに、gettext
呼び出しの一部です。
{{ gettext('Hello World!') }}
{{ gettext('Hello %(name)s!', name='World') }}
{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
ngettext
関数のフォーマット文字列は、指定されたパラメーターに加えて、num
パラメーターとしてカウントを自動的に受け取ります。
式ステートメント
式ステートメント拡張がロードされると、通常の変数式(テンプレート:...
)とまったく同じように機能する do というタグが使用可能になります。 何も印刷しないことを除いて。 これは、リストを変更するために使用できます。
{% do navigation.append('a string') %}
ループ制御
アプリケーションがループコントロールを有効にしている場合、 break および continue をループで使用できます。 break に達すると、ループは終了します。 continue に達すると、処理は停止され、次の反復に進みます。
これは、1つおきの項目をスキップするループです。
{% for user in users %}
{%- if loop.index is even %}{% continue %}{% endif %}
...
{% endfor %}
同様に、10回目の反復後に処理を停止するループ:
{% for user in users %}
{%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}
loop.index
は1で始まり、loop.index0
は0で始まることに注意してください( For を参照)。
デバッグステートメント
Debug Extension が有効になっている場合、{% debug %}
タグを使用して、現在のコンテキストと使用可能なフィルターおよびテストをダンプできます。 これは、デバッガーを設定せずにテンプレートで使用できるものを確認するのに役立ちます。
<pre>{% debug %}</pre>
{'context': {'cycler': <class 'jinja2.utils.Cycler'>,
...,
'namespace': <class 'jinja2.utils.Namespace'>},
'filters': ['abs', 'attr', 'batch', 'capitalize', 'center', 'count', 'd',
..., 'urlencode', 'urlize', 'wordcount', 'wordwrap', 'xmlattr'],
'tests': ['!=', '<', '<=', '==', '>', '>=', 'callable', 'defined',
..., 'odd', 'sameas', 'sequence', 'string', 'undefined', 'upper']}
ステートメント付き
バージョン2.3の新機能。
withステートメントを使用すると、新しい内部スコープを作成できます。 このスコープ内に設定された変数は、スコープ外には表示されません。
一言で言えば:
{% with %}
{% set foo = 42 %}
{{ foo }} foo is 42 here
{% endwith %}
foo is not visible here any longer
スコープの先頭に変数を設定するのが一般的であるため、 with ステートメント内でそれを行うことができます。 次の2つの例は同等です。
{% with foo = 42 %}
{{ foo }}
{% endwith %}
{% with %}
{% set foo = 42 %}
{{ foo }}
{% endwith %}
ここでのスコープに関する重要な注意事項。 2.9より前のJinjaバージョンでは、ある変数を別の変数に参照する動作は、意図しない結果をもたらしました。 特に、ある変数は、ブロックの冒頭陳述と同じように定義された別の変数を参照する可能性があります。 これにより、クリーンアップされたスコープ動作に問題が発生し、その後改善されました。 特に新しいJinjaバージョンでは、次のコードは常に with ブロックの外側から変数 a を参照します。
{% with a={}, b=a.attribute %}...{% endwith %}
以前のJinjaバージョンでは、 b 属性は最初の属性の結果を参照していました。 この動作に依存している場合は、set
タグを使用するように書き直すことができます。
{% with a={} %}
{% set b = a.attribute %}
{% endwith %}
拡大
古いバージョンのJinja(2.9より前)では、拡張機能を使用してこの機能を有効にする必要がありました。 デフォルトで有効になりました。
自動エスケープオーバーライド
バージョン2.4の新機能。
必要に応じて、テンプレート内から自動エスケープをアクティブ化および非アクティブ化できます。
例:
{% autoescape true %}
Autoescaping is active within this block
{% endautoescape %}
{% autoescape false %}
Autoescaping is inactive within this block
{% endautoescape %}
endautoescape の後、動作は以前の状態に戻ります。
拡大
古いバージョンのJinja(2.9より前)では、拡張機能を使用してこの機能を有効にする必要がありました。 デフォルトで有効になりました。
コメント
テンプレート内の行の一部をコメントアウトするには、デフォルトで
{# ... #}
に設定されているコメント構文を使用します。 これは、デバッグのためにテンプレートの一部をコメントアウトしたり、他のテンプレート設計者または自分自身に情報を追加したりするのに役立ちます。