テンプレート
FlaskはJinja2をテンプレートエンジンとして活用します。 明らかに別のテンプレートエンジンを自由に使用できますが、Flask自体を実行するにはJinja2をインストールする必要があります。 この要件は、豊富な拡張機能を有効にするために必要です。 拡張機能は、Jinja2が存在することに依存する可能性があります。
このセクションでは、Jinja2がFlaskに統合される方法について簡単に紹介します。 テンプレートエンジンの構文自体に関する情報が必要な場合は、公式の Jinja2テンプレートドキュメントにアクセスして詳細を確認してください。
ジンジャセットアップ
カスタマイズされていない限り、Jinja2はFlaskによって次のように構成されます。
- 自動エスケープは、
render_template()
を使用する場合、.html
、.htm
、.xml
、および.xhtml
で終わるすべてのテンプレートで有効になります。 render_template_string()
を使用すると、すべての文字列で自動エスケープが有効になります。- テンプレートには、
{% autoescape %}
タグを使用した自動エスケープをオプトイン/オプトアウトする機能があります。 - Flaskは、デフォルトで存在する値に加えて、いくつかのグローバル関数とヘルパーをJinja2コンテキストに挿入します。
標準コンテキスト
次のグローバル変数は、デフォルトでJinja2テンプレート内で使用できます。
- config
現在の構成オブジェクト(
flask.config
)バージョン0.6の新機能。
バージョン0.10で変更:これは、インポートされたテンプレートでも常に使用できるようになりました。
- request
- 現在のリクエストオブジェクト( flask.request )。 テンプレートがアクティブなリクエストコンテキストなしでレンダリングされた場合、この変数は使用できません。
- session
- 現在のセッションオブジェクト( flask.session )。 テンプレートがアクティブなリクエストコンテキストなしでレンダリングされた場合、この変数は使用できません。
- g
- グローバル変数のリクエストバインドオブジェクト( flask.g )。 テンプレートがアクティブなリクエストコンテキストなしでレンダリングされた場合、この変数は使用できません。
- url_for()
flask.url_for()
機能。
- get_flashed_messages()
flask.get_flashed_messages()
機能。
Jinjaコンテキストの動作
これらの変数は変数のコンテキストに追加され、グローバル変数ではありません。 違いは、デフォルトでは、これらはインポートされたテンプレートのコンテキストでは表示されないことです。 これは、部分的にはパフォーマンスの考慮事項によって引き起こされ、部分的には物事を明確に保つためです。
これはあなたにとってどういう意味ですか? インポートするマクロがある場合、それはリクエストオブジェクトにアクセスする必要があります。2つの可能性があります。
- リクエストをパラメータとして、または関心のあるリクエストオブジェクトの属性としてマクロに明示的に渡します。
- マクロを「コンテキスト付き」でインポートします。
コンテキストを使用したインポートは次のようになります。
{% from '_helpers.html' import my_macro with context %}
標準フィルター
これらのフィルターは、Jinja2自体が提供するフィルターに加えて、Jinja2で使用できます。
- tojson()
この関数は、指定されたオブジェクトをJSON表現に変換します。 これは、たとえば、JavaScriptをその場で生成しようとする場合に非常に役立ちます。
<script type=text/javascript> doSomethingWith({{ user.username|tojson }}); </script>
| tojson の出力を一重引用符で囲まれた HTML属性で使用することも安全です。
<button onclick='doSomethingWith({{ user.username|tojson }})'> Click me </button>
0.10より前のバージョンのFlaskでは、
script
内で|tojson
の出力を使用する場合は、|safe
でエスケープを無効にしてください。 Flask 0.10以降では、これは自動的に行われます。
自動エスケープの制御
自動エスケープは、特別な文字を自動的にエスケープするという概念です。 HTML(またはXML、したがってXHTML)の意味での特殊文字は、&
、>
、<
、"
、および [ X127X]。 これらの文字はそれ自体でドキュメント内で特定の意味を持っているため、テキストに使用する場合は、いわゆる「エンティティ」に置き換える必要があります。 そうしないと、テキストでこれらの文字を使用できないことによるユーザーの不満を引き起こすだけでなく、セキュリティの問題を引き起こす可能性もあります。 (クロスサイトスクリプティング(XSS)を参照)
ただし、テンプレートで自動エスケープを無効にする必要がある場合があります。 これは、HTMLをページに明示的に挿入する場合、たとえば、マークダウンからHTMLへのコンバーターのような安全なHTMLを生成するシステムからのものである場合に当てはまります。
これを実現するには、次の3つの方法があります。
- Pythonコードでは、HTML文字列を
Markup
オブジェクトでラップしてから、テンプレートに渡します。 これは一般的に推奨される方法です。 - テンプレート内で、
|safe
フィルターを使用して、文字列を安全なHTMLとして明示的にマークします(テンプレート:Myvariable
) - 自動エスケープシステムを一時的に完全に無効にします。
テンプレートで自動エスケープシステムを無効にするには、{% autoescape %}
ブロックを使用できます。
{% autoescape false %}
<p>autoescaping is disabled here
<p>{{ will_not_be_escaped }}
{% endautoescape %}
これを行うときは常に、このブロックで使用している変数に十分注意してください。
フィルタの登録
Jinja2に独自のフィルターを登録する場合は、2つの方法があります。 アプリケーションのjinja_env
に手動で配置するか、template_filter()
デコレータを使用できます。
次の2つの例は同じように機能し、どちらもオブジェクトを反転します。
@app.template_filter('reverse')
def reverse_filter(s):
return s[::-1]
def reverse_filter(s):
return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter
デコレータの場合、関数名をフィルタの名前として使用する場合は、引数はオプションです。 登録すると、Jinja2の組み込みフィルターと同じ方法でテンプレートでフィルターを使用できます。たとえば、 mylist というコンテキストにPythonリストがある場合です。
{% for x in mylist | reverse %}
{% endfor %}
コンテキストプロセッサ
テンプレートのコンテキストに新しい変数を自動的に挿入するために、Flaskにはコンテキストプロセッサがあります。 コンテキストプロセッサは、テンプレートがレンダリングされる前に実行され、テンプレートコンテキストに新しい値を挿入する機能があります。 コンテキストプロセッサは、辞書を返す関数です。 次に、この辞書のキーと値が、アプリ内のすべてのテンプレートのテンプレートコンテキストとマージされます。
@app.context_processor
def inject_user():
return dict(user=g.user)
上記のコンテキストプロセッサは、 user という変数を g.user の値でテンプレートで使用できるようにします。 g はとにかくテンプレートで使用できるため、この例はあまり興味深いものではありませんが、これがどのように機能するかがわかります。
変数は値に限定されません。 コンテキストプロセッサは、テンプレートで関数を使用できるようにすることもできます(Pythonでは関数の受け渡しが許可されているため)。
@app.context_processor
def utility_processor():
def format_price(amount, currency=u'€'):
return u'{0:.2f}{1}'.format(amount, currency)
return dict(format_price=format_price)
上記のコンテキストプロセッサは、 format_price 関数をすべてのテンプレートで使用できるようにします。
{{ format_price(0.33) }}
format_price をテンプレートフィルターとして作成することもできますが(フィルターの登録を参照)、これはコンテキストプロセッサーで関数を渡す方法を示しています。