常见问题 — Jinja 文档
经常问的问题
本页回答了一些关于 Jinja 的常见问题。
为什么叫金贾?
选择 Jinja 这个名字是因为它是日本寺庙的名称,而且寺庙和模板的发音相似。 它不是以乌干达的城市命名的。
它有多快?
我们真的很讨厌基准测试,尤其是因为它们反映的并不多。 模板的性能取决于许多因素,您必须在不同情况下对不同引擎进行基准测试。 测试套件的基准测试表明,Jinja 具有与 Mako 相似的性能,并且比 Django 的模板引擎或 Genshi 快 10 到 20 倍。 这些数字应该与大量的盐一起使用,因为采用这些数字的基准只测试了一些与性能相关的情况,例如循环。 一般来说,模板引擎的性能并不重要,因为 Web 应用程序中通常的瓶颈是数据库或应用程序代码。
Jinja 与 Django 的兼容性如何?
Jinja 的默认语法在很多方面都与 Django 语法相匹配。 然而,这种相似性并不意味着您可以在 Jinja 中使用未经修改的 Django 模板。 例如过滤器参数使用函数调用语法而不是冒号来分隔过滤器名称和参数。 此外,Jinja 中的扩展接口与 Django 有根本的不同,这意味着您的自定义标签将不再起作用。
一般来说,您将使用更少的自定义扩展,因为 Jinja 模板系统允许您使用 Python 表达式的某个子集,这些子集可以替换大多数 Django 扩展。 例如,而不是使用这样的东西:
您很可能会提供一个具有属性的对象以从数据库中检索评论:
或者直接提供模型进行快速测试:
请记住,即使您可以将这些内容放入模板中,但这仍然不是一个好主意。 查询应该进入视图代码而不是模板!
将逻辑放入模板中不是一个糟糕的主意吗?
毫无疑问,您应该尝试从模板中删除尽可能多的逻辑。 但是没有任何逻辑的模板意味着您必须在代码中进行所有处理,这既无聊又愚蠢。 执行此操作的模板引擎与 Python 一起提供并称为 string.Template。 没有循环和 if 条件,是迄今为止您可以为 Python 获得的最快的模板引擎。
所以模板中需要一些逻辑来让每个人都开心。 Jinja 将多少逻辑放在模板中几乎由您决定。 您可以做什么和不可以做什么有一些限制。
Jinja 既不允许您将任意 Python 代码放入模板中,也不允许所有 Python 表达式。 运算符仅限于最常见的运算符,并且不支持更高级的表达式,例如列表推导式和生成器表达式。 这使模板引擎更易于维护并且模板更具可读性。
为什么自动转义不是默认值?
自动转义不是默认模式,也不推荐使用的原因有多种。 虽然变量的自动转义意味着你不太可能遇到 XSS 问题,但它也会导致模板引擎中的大量额外处理,这可能会导致严重的性能问题。 由于 Python 没有提供将字符串标记为不安全的方法,因此 Jinja 必须通过提供与安全和不安全字符串安全交互的自定义字符串类(Markup
字符串)来绕过该限制。
然而,通过显式转义,模板引擎不必对变量执行任何安全检查。 人们也知道不要转义整数或字符串,这些整数或字符串可能永远不会包含必须转义的字符或已经是 HTML 标记的字符。 例如,当为统计表迭代整数表和浮点数的列表时,模板设计者可以省略转义,因为他知道整数或浮点数不包含任何不安全的参数。
此外,Jinja 是一个通用模板引擎,不仅用于 HTML/XML 生成。 例如,您可以生成 LaTeX、电子邮件、CSS、JavaScript 或配置文件。
为什么 Context 是不可变的?
在编写 pass_context()
函数时,您可能已经注意到上下文试图阻止您修改它。 如果您通过使用内部上下文 API 设法修改了上下文,您可能已经注意到上下文中的更改在模板中似乎不可见。 这样做的原因是 Jinja 出于性能原因仅将上下文用作模板变量的主要数据源。
如果要修改上下文,请编写一个返回变量的函数,而不是使用 set 将其分配给变量:
我的回溯看起来很奇怪。 发生了什么?
Jinja 可以重写回溯,以便它们显示模板行号和源代码而不是底层编译代码,但这需要特殊的 Python 支持。 CPython <3.7 需要ctypes
,而 PyPy 需要透明代理支持。
如果您使用的是 Google App Engine,则 ctypes
不可用。 您可以使其在开发中可用,但不能在生产中使用。
此代码段归功于 Thomas Johansson
我的宏被某些东西覆盖了
在某些情况下,Jinja 范围看起来是任意的:
布局.tmpl:
child.tmpl:
这将在 Jinja 中打印 LAYOUT
。 这是在子模板之后评估父模板的副作用。 这允许子模板将信息传递给父模板。 为避免此问题,将父模板中的宏或变量重命名为具有不常见的前缀。