よくある質問—Jinjaのドキュメント
よくある質問
このページは、Jinjaに関してよくある質問のいくつかに答えます。
なぜジンジャと呼ばれるのですか?
日本の寺院の名前であり、寺院とテンプレートが同じ発音を共有しているため、Jinjaという名前が選ばれました。 ウガンダの都市にちなんで名付けられたものではありません。
どれくらい速いですか?
ベンチマークはあまり反映されていないため、特に嫌いです。 テンプレートのパフォーマンスは多くの要因に依存し、さまざまな状況でさまざまなエンジンのベンチマークを行う必要があります。 テストスイートのベンチマークは、Jinjaが Mako と同様のパフォーマンスを持ち、DjangoのテンプレートエンジンまたはGenshiよりも10〜20倍高速であることを示しています。 これらの数値を取得したベンチマークは、ループなどのパフォーマンス関連のいくつかの状況のみをテストするため、これらの数値は大量のソルトとともに取得する必要があります。 一般的に言えば、Webアプリケーションの通常のボトルネックはデータベースまたはアプリケーションコードであるため、テンプレートエンジンのパフォーマンスはそれほど重要ではありません。
JinjaはDjangoとどの程度互換性がありますか?
Jinjaのデフォルトの構文は、多くの点でDjangoの構文と一致します。 ただし、この類似性は、Jinjaで変更されていないDjangoテンプレートを使用できることを意味するものではありません。 たとえば、フィルター引数は、コロンではなく関数呼び出し構文を使用して、フィルター名と引数を区切ります。 さらに、Jinjaの拡張インターフェースはDjangoのものとは根本的に異なります。つまり、カスタムタグは機能しなくなります。
一般的に言えば、JinjaテンプレートシステムではほとんどのDjango拡張機能を置き換えることができるPython式の特定のサブセットを使用できるため、使用するカスタム拡張機能ははるかに少なくなります。 たとえば、次のようなものを使用する代わりに:
{% load comments %}
{% get_latest_comments 10 as latest_comments %}
{% for comment in latest_comments %}
...
{% endfor %}
ほとんどの場合、データベースからコメントを取得するための属性を持つオブジェクトを提供します。
{% for comment in models.comments.latest(10) %}
...
{% endfor %}
または、迅速なテストのためにモデルを直接提供します。
{% for comment in Comment.objects.order_by('-pub_date')[:10] %}
...
{% endfor %}
そのようなものをテンプレートに入れても、それでも良い考えではないことを覚えておいてください。 クエリは、テンプレートではなくビューコードに入力する必要があります。
ロジックをテンプレートに入れるのはひどい考えではありませんか?
間違いなく、テンプレートからできるだけ多くのロジックを削除するようにしてください。 しかし、ロジックのないテンプレートは、退屈で愚かなコードですべての処理を実行する必要があることを意味します。 これを行うテンプレートエンジンはPythonに付属しており、 string.Template と呼ばれます。 ループがなく、条件があれば、Python用に入手できる最速のテンプレートエンジンです。
そのため、テンプレートには、全員を満足させるためにある程度のロジックが必要です。 そして、Jinjaは、テンプレートにどれだけのロジックを入れたいかをあなたに任せています。 できることとできないことにはいくつかの制限があります。
Jinjaでは、任意のPythonコードをテンプレートに入れることも、すべてのPython式を使用することもできません。 演算子は最も一般的なものに限定されており、リスト内包表記やジェネレータ式などのより高度な式はサポートされていません。 これにより、テンプレートエンジンの保守が容易になり、テンプレートが読みやすくなります。
自動エスケープがデフォルトではないのはなぜですか?
自動エスケープがデフォルトモードではなく、推奨モードでもない理由は複数あります。 変数の自動エスケープは、XSSの問題が発生する可能性が低いことを意味しますが、テンプレートエンジンで大量の余分な処理を引き起こし、深刻なパフォーマンスの問題を引き起こす可能性があります。 Pythonは文字列を安全でないものとしてマークする方法を提供しないため、Jinjaは、安全な文字列と安全でない文字列と安全に相互作用するカスタム文字列クラス(Markup
文字列)を提供することにより、その制限を回避する必要があります。
ただし、明示的なエスケープを使用すると、テンプレートエンジンは変数に対して安全性チェックを実行する必要がありません。 また、人間は、エスケープする必要のある文字やすでにHTMLマークアップを含むことのない整数や文字列をエスケープしないことを知っています。 たとえば、整数のテーブルと統計のテーブルの浮動小数点数のリストを反復処理する場合、テンプレートの設計者は、整数または浮動小数点数に安全でないパラメーターが含まれていないことを知っているため、エスケープを省略できます。
さらに、Jinjaは汎用テンプレートエンジンであり、HTML / XMLの生成に使用されるだけではありません。 たとえば、LaTeX、電子メール、CSS、JavaScript、または構成ファイルを生成できます。
コンテキストが不変なのはなぜですか?
pass_context()
関数を作成しているときに、コンテキストが関数の変更を阻止しようとしていることに気付いたかもしれません。 内部コンテキストAPIを使用してコンテキストを変更できた場合は、コンテキストの変更がテンプレートに表示されていないように見えることに気付いたかもしれません。 これは、パフォーマンス上の理由から、Jinjaがコンテキストをテンプレート変数のプライマリデータソースとしてのみ使用するためです。
コンテキストを変更する場合は、setを使用して変数に割り当てることができる代わりに、変数を返す関数を記述します。
{% set comments = get_latest_comments() %}
私のトレースバックは奇妙に見えます。 何が起こっていますか?
Jinjaはトレースバックを書き換えて、基になるコンパイル済みコードではなくテンプレート行番号とソースを表示できますが、これには特別なPythonサポートが必要です。 CPython <3.7にはctypes
、およびPyPyには透過プロキシサポートが必要です。
Google App Engineを使用している場合、ctypes
は使用できません。 開発では利用可能にすることができますが、本番環境では利用できません。
import os
if os.environ.get('SERVER_SOFTWARE', '').startswith('Dev'):
from google.appengine.tools.devappserver2.python import sandbox
sandbox._WHITE_LIST_C_MODULES += ['_ctypes', 'gestalt']
このスニペットのクレジットは Thomas Johansson に送られます
私のマクロは何かによって上書きされます
状況によっては、Jinjaのスコープは恣意的に見えます。
layout.tmpl:
{% macro foo() %}LAYOUT{% endmacro %}
{% block body %}{% endblock %}
child.tmpl:
{% extends 'layout.tmpl' %}
{% macro foo() %}CHILD{% endmacro %}
{% block body %}{{ foo() }}{% endblock %}
これにより、JinjaでLAYOUT
が印刷されます。 これは、親テンプレートを子テンプレートの後に評価することの副作用です。 これにより、子テンプレートが親テンプレートに情報を渡すことができます。 この問題を回避するには、親テンプレートのマクロまたは変数の名前を、一般的でないプレフィックスを持つように変更します。