常见问题

这一页回答了一些关于Jinja的常见问题。

为什么叫Jinja?

之所以选择Jinja这个名字,是因为它是一个日本寺庙的名字,而且这个寺庙和模板有着相似的发音。它不是以乌干达的城市命名的。

它有多快?

我们真的很讨厌基准,特别是因为它们反映的不多。模板的性能取决于许多因素,您必须在不同的情况下对不同的引擎进行基准测试。测试套件的基准测试表明,jinja2的性能与 Mako 它比Django的模板引擎或Genshi快10到20倍。这些数字应该以吨盐作为基准,这些数字只测试一些与性能相关的情况,如循环。一般来说,模板引擎的性能并不重要,因为Web应用程序中通常的瓶颈是数据库或应用程序代码。

Jinja2与Django的兼容性如何?

jinja2的默认语法在许多方面与django语法匹配。但是,这种相似性并不意味着您可以使用未在jinja2中修改的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 . 它没有循环和if条件,是迄今为止为python所能获得的最快的模板引擎。

所以在模板中需要一定数量的逻辑来保持每个人的快乐。而Jinja留给你的是你想在模板中加入多少逻辑。你能做什么和不能做什么都有一些限制。

jinja2既不允许将任意的python代码放入模板中,也不允许所有的python表达式。运算符仅限于最常见的运算符,不支持更高级的表达式,如列表理解和生成器表达式。这使得模板引擎更容易维护,模板更可读。

为什么自动转义不是默认的?

Markup 字符串)与安全和不安全的字符串安全交互。

但是,对于显式转义,模板引擎不必对变量执行任何安全检查。此外,人类知道不转义整数或字符串,这些整数或字符串可能永远不包含必须转义的字符或已经包含HTML标记的字符。例如,当为统计表对整数和浮点表的列表进行迭代时,模板设计器可以省略转义,因为他知道整数或浮点不包含任何不安全的参数。

此外,jinja2是一个通用模板引擎,不仅用于生成HTML/XML。例如,您可以生成 Latex 、电子邮件、css、javascript或配置文件。

为什么上下文是不变的?

编写 contextfunction() 时或者类似的事情,你可能已经注意到,上下文试图阻止你修改它。如果您已经使用内部上下文API成功地修改了上下文,那么您可能已经注意到上下文中的更改在模板中似乎不可见。原因是,出于性能原因,Jinja仅将上下文用作模板变量的主数据源。

如果要修改上下文,请编写一个函数,该函数返回一个变量,而不是一个可以使用set:分配给变量的函数:

{% set comments = get_latest_comments() %}

我的回溯看起来很奇怪。发生什么事了?

如果未编译debugsupport模块,并且您使用的是没有ctypes的python安装(没有ctypes的python 2.4、jython或Google的appengine),则jinja2无法提供正确的调试信息,并且追溯可能不完整。目前对于Jython或AppEngine没有很好的解决方案,因为CTypes在那里不可用,并且不可能使用DebugSupport扩展。

如果您在Google Appengine Development Server中工作,您可以将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

为什么没有python 2.3/2.4/2.5/2.6/3.1/3.2/3.3支持?

python 2.3缺少了许多在jinja2中大量使用的特性。这个决定是在即将发布的Python2.6和3.0版本中做出的,因此很难维护旧版本的代码。如果您真的需要Python2.3支持,您要么使用 Jinja 1 或其他仍然支持2.3的模板化引擎。

当我们使用相同的源代码(不使用2to 3)切换到支持python 2和3时,python 2.4/2.5/3.1/3.2支持被删除。因为只有python 2.6/2.7和>=3.3支持字节和unicode文本,并且它们在某种程度上彼此兼容,所以需要放弃支持。如果您确实需要对旧的python 2(或3)版本的支持,您可以使用jinja2 2.6。

python 2.6/3.3支持被放弃,因为它在各种上游项目(如wheel或pytest)中被放弃,这将使继续支持它变得困难。jinja2.10是支持python 2.6/3.3的最后一个版本。

我的宏被某些内容覆盖

在某些情况下,Jinja范围界定似乎是任意的:

layout.tmpl

{% macro foo() %}LAYOUT{% endmacro %}
{% block body %}{% endblock %}

child.tmpl:

{% extends 'layout.tmpl' %}
{% macro foo() %}CHILD{% endmacro %}
{% block body %}{{ foo() }}{% endblock %}

这将打印 LAYOUT 在Jinja2。这是在子模板之后对父模板进行评估的副作用。这允许子模板将信息传递给父模板。若要避免此问题,请将父模板中的宏或变量重命名为具有不常见的前缀。