扩展 — Jinja 文档
扩展
Jinja 支持可以添加额外过滤器、测试、全局变量甚至扩展解析器的扩展。 扩展的主要动机是将经常使用的代码移动到可重用的类中,例如添加对国际化的支持。
添加扩展
扩展在创建时添加到 Jinja 环境中。 要添加扩展,请将扩展类列表或导入路径传递给 Environment 构造函数的 extensions
参数。 以下示例创建了一个加载了 i18n 扩展的 Jinja 环境:
要在创建时间后添加扩展,请使用 add_extension() 方法:
i18n 扩展
进口名称: jinja2.ext.i18n
i18n 扩展可以与 gettext 或 Babel 结合使用。 启用后,Jinja 提供 trans
语句,将块标记为可翻译并调用 gettext
。
启用后,应用程序必须为 gettext
、ngettext
以及可选的 pgettext
和 npgettext
提供功能,无论是全局还是渲染时。 添加了 _()
函数作为 gettext
函数的别名。
环境方法
启用扩展后,环境提供以下附加方法:
- jinja2.Environment.install_gettext_translations(translations, newstyle=False)
为环境全局安装翻译。
translations
对象必须实现gettext
、ngettext
和可选的pgettext
和npgettext
。 支持gettext.NullTranslations
、gettext.GNUTranslations
和 BabelsTranslations
。3.0 版本变更: 添加
pgettext
和npgettext
。2.5 版更改: 添加了新样式的 gettext 支持。
- jinja2.Environment.install_null_translations(newstyle=False)
安装无操作 gettext 函数。 如果您想为国际化准备应用程序但还不想实现完整的系统,这将非常有用。
2.5 版更改: 添加了新样式的 gettext 支持。
- jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False, pgettext=None, npgettext=None)
将给定的
gettext
、ngettext
、pgettext
和npgettext
可调用对象安装到环境中。 它们的行为应该与gettext.gettext()
、gettext.ngettext()
、gettext.pgettext()
和gettext.npgettext()
完全一样。如果
newstyle
被激活,callables 被包装成像 newstyle callables 一样工作。 有关更多信息,请参阅 新样式 Gettext。3.0 版本变更: 添加
pgettext
和npgettext
。2.5 新功能: 添加了新样式的 gettext 支持。
- jinja2.Environment.uninstall_gettext_translations()
- 卸载环境的全局安装翻译。
- jinja2.Environment.extract_translations(source)
从给定的模板节点或源中提取可本地化的字符串。
对于找到的每个字符串,此函数生成一个
(lineno, function, message)
元组,其中:lineno
是找到字符串所在行的编号。function
是使用的gettext
函数的名称(如果字符串是从嵌入的 Python 代码中提取的)。message
是字符串本身,或者是具有多个参数的函数的字符串元组。
对于提供多种语言但为所有用户提供相同语言的 Web 应用程序(例如,为法语社区安装的多语言论坛软件),可能会在创建环境时安装翻译。
get_gettext_translations
函数将返回当前配置的转换器,例如使用 gettext.find
。
i18n
扩展对模板设计者的使用在模板文档中有介绍。
空白修剪
2.10 版中的新功能。
在 {% trans %}
块中,修剪换行符和空格会很有用,这样文本块看起来就像翻译文件中带有单个空格的简单字符串。
通过启用 ext.i18n.trimmed
策略 ,可以自动修剪换行符和周围的空白。
新样式获取文本
2.5 版中的新功能。
新样式的 gettext 调用更少键入,更不容易出错,并且更好地支持自动转义。
您可以通过设置 env.newstyle_gettext = True
或将 newstyle=True
传递给 env.install_translations
来使用“新样式”gettext 调用。 Babel 提取工具完全支持它们,但可能无法与其他提取工具按预期工作。
对于标准的 gettext
调用,字符串格式化是使用 |format
过滤器完成的单独步骤。 这需要为 ngettext
调用重复工作。
新样式 gettext
使格式化成为调用的一部分,并在幕后加强一致性。
newstyle gettext 的优点是:
- 没有单独的格式化步骤,您不必记住使用
|format
过滤器。 - 只允许命名占位符。 这解决了翻译人员面临的一个常见问题,因为位置占位符无法有意义地切换位置。 命名占位符总是携带关于什么值去哪里的语义信息。
- 即使不使用占位符,也会使用字符串格式,这使得所有字符串都使用一致的格式。 请记住将任何原始百分号转义为
%%
,例如100%%
。 - 翻译后的字符串被标记为安全,格式化会根据需要执行转义。 如果参数已被转义,则将其标记为
|safe
。
表达式语句
进口名称: jinja2.ext.do
“do”又名表达式语句扩展向模板引擎添加了一个简单的 do
标签,该标签的工作方式类似于变量表达式,但会忽略返回值。
循环控制
进口名称: jinja2.ext.loopcontrols
此扩展在循环中添加了对 break
和 continue
的支持。 启用后,Jinja 提供了这两个关键字,它们的工作方式与 Python 中的完全相同。
有声明
进口名称: jinja2.ext.with_
2.9 版更改: 此扩展现已内置,不再执行任何操作。
自动逃生扩展
进口名称: jinja2.ext.autoescape
在 2.9 版更改:此扩展已被删除,现在是内置的。 启用扩展不再做任何事情。
调试扩展
进口名称: jinja2.ext.debug
添加 {% debug %}
标签以转储当前上下文以及可用的过滤器和测试。 这对于在不设置调试器的情况下查看模板中可用的内容很有用。
编写扩展
通过编写扩展,您可以向 Jinja 添加自定义标签。 这是一项重要任务,通常不需要,因为默认标签和表达式涵盖了所有常见用例。 i18n 扩展是一个很好的例子,说明了扩展为何有用。 另一种是片段缓存。
在编写扩展时,您必须记住,您正在使用 Jinja 模板编译器,它不会验证您传递给它的节点树。 如果 AST 格式不正确,您将收到各种令人讨厌的编译器或运行时错误。 始终确保您使用的是正确创建的节点。 下面的 API 文档显示了存在哪些节点以及如何使用它们。
示例扩展
内联 gettext
以下示例演示使用 Extension.filter_stream() 解析对 _()
gettext 函数的调用与静态数据内联,无需 Jinja 块。
它需要加载和配置 i18n 扩展。
扩展API
延期
扩展总是要扩展 jinja2.ext.Extension 类:
- class jinja2.ext.Extension(environment)
扩展可用于在解析器级别向 Jinja 模板系统添加额外功能。 自定义扩展绑定到环境,但可能不会在 self 上存储环境特定数据。 这样做的原因是通过创建副本并重新分配 environment 属性,可以将扩展绑定到另一个环境(用于覆盖)。
由于扩展是由环境创建的,因此它们不能接受任何配置参数。 人们可能想通过使用工厂函数来解决这个问题,但这是不可能的,因为扩展是由它们的导入名称标识的。 配置扩展的正确方法是将配置值存储在环境中。 因为通过这种方式,环境最终充当中央配置存储,属性可能会发生冲突,这就是为什么扩展必须确保它们为配置选择的名称不太通用。 例如
prefix
是一个糟糕的名字,另一方面fragment_cache_prefix
是一个好名字,因为它包含了扩展名(片段缓存)。- 参数
environment (jinja2.environment.Environment) –
- 返回类型
没有任何
- identifier
扩展的标识符。 这始终是扩展类的真正导入名称,不得更改。
- tags
如果扩展实现了自定义标签,则这是扩展正在侦听的一组标签名称。
- attr(name, lineno=None)
返回当前扩展的属性节点。 这对于将扩展上的常量传递给生成的模板代码很有用。
- 参数
名称 (str) –
lineno (可选[int]) –
- 返回类型
jinja2.nodes.ExtensionAttribute
- call_method(name, args=None, kwargs=None, dyn_args=None, dyn_kwargs=None, lineno=None)
调用扩展的方法。 这是 attr() +
jinja2.nodes.Call
的快捷方式。- 参数
名称 (str) –
args (可选[列表[jinja2.nodes.Expr ]]) –
kwargs (可选[列表[jinja2.nodes.Keyword ]]) –
dyn_args (可选[jinja2.nodes.Expr]) –
dyn_kwargs (可选[jinja2.nodes.Expr]) –
lineno (可选[int]) –
- 返回类型
jinja2.nodes.Call
- filter_stream(stream)
它传递了一个 TokenStream,可用于过滤返回的令牌。 此方法必须返回 Token 的迭代,但它不必返回 TokenStream。
- 参数
stream (TokenStream) –
- 返回类型
Union[TokenStream, Iterable[Token]]
- parse(parser)
如果任何 tags 匹配,则使用解析器作为第一个参数调用此方法。 解析器流指向的标记是匹配的名称标记。 此方法必须返回一个或多个节点的列表。
- 参数
解析器 (解析器) –
- 返回类型
联合[jinja2.nodes.Node, List[jinja2.nodes.Node]]
- preprocess(source, name, filename=None)
此方法在实际词法分析之前调用,可用于预处理源。 文件名 是可选的。 返回值必须是预处理过的源。
- 参数
source (str) –
名称 (可选[str]) –
文件名 (可选[str]) –
- 返回类型
字符串
解析器
传递给 Extension.parse() 的解析器提供了解析不同类型表达式的方法。 扩展可以使用以下方法:
- class jinja2.parser.Parser(environment, source, name=None, filename=None, state=None)
这是 Jinja 使用的中央解析类。 它传递给扩展,可用于解析表达式或语句。
- 参数
环境 (环境) –
source (str) –
名称 (可选[str]) –
文件名 (可选[str]) –
state (可选[str]) –
- 返回类型
没有任何
- filename
解析器处理的模板的文件名。 这是 不是 模板的加载名称。 有关负载名称,请参阅 name。 对于未从文件系统加载的模板,这是
None
。
- name
模板的加载名称。
- stream
当前的 TokenStream
- fail(msg, lineno=None, exc=<class 'jinja2.exceptions.TemplateSyntaxError'>)
使用消息、传递的行号或最后一行号以及当前名称和文件名引发 exc 的便捷方法。
- 参数
msg (str) –
lineno (可选[int]) –
exc (Type[jinja2.exceptions.TemplateSyntaxError]) –
- 返回类型
te.NoReturn
- free_identifier(lineno=None)
返回一个新的空闲标识符作为
InternalName
。- 参数
lineno (可选[int]) –
- 返回类型
jinja2.nodes.InternalName
- parse_assign_target(with_tuple=True, name_only=False, extra_end_rules=None, with_namespace=False)
解析分配目标。 由于 Jinja 允许对元组进行赋值,因此该函数可以解析所有允许的赋值目标。 解析元组的默认分配,但是可以通过将 with_tuple 设置为 False 来禁用。 如果只需要给名称赋值 name_only 可以设置为 True。 extra_end_rules 参数被转发到元组解析函数。 如果启用 with_namespace,则可以解析命名空间分配。
- 参数
with_tuple (bool) –
name_only (bool) –
extra_end_rules (可选[元组[str, ...]]) –
with_namespace (bool) –
- 返回类型
联合[jinja2.nodes.NSRef, jinja2.nodes.Name, jinja2.nodes.Tuple]
- parse_expression(with_condexpr=True)
解析表达式。 默认情况下,所有表达式都被解析,如果可选的 with_condexpr 参数设置为 False 条件表达式不被解析。
- 参数
with_condexpr (bool) –
- 返回类型
jinja2.nodes.Expr
- parse_statements(end_tokens, drop_needle=False)
将多个语句解析为一个列表,直到达到结束标记之一。 这用于解析语句体,因为它还会在适当的情况下解析模板数据。 解析器首先检查当前标记是否为冒号,如果有则跳过它。 然后它检查块结束并解析直到是否达到 end_tokens 之一。 默认情况下,调用结束时流中的活动标记是匹配的结束标记。 如果不需要 drop_needle 可以设置为 True 并删除结束标记。
- 参数
end_tokens (元组[str,...][ X85X]) –
drop_needle (bool) –
- 返回类型
列表[jinja2.nodes.Node]
- parse_tuple(simplified=False, with_condexpr=True, extra_end_rules=None, explicit_parentheses=False)
像 parse_expression 一样工作,但如果多个表达式由逗号分隔,则会创建
Tuple
节点。 如果找不到逗号,此方法还可以返回正则表达式而不是元组。默认的解析模式是一个完整的元组。 如果 simplified 是 True,则仅解析名称和文字。 no_condexpr 参数被转发到 parse_expression()。
因为元组不需要分隔符并且可能以假逗号结尾,所以需要额外的提示来标记元组的结尾。 例如,for 循环支持 for 和 in 之间的元组。 在这种情况下,extra_end_rules 设置为
['name:in']
。explicit_parentheses 如果解析是由括号中的表达式触发的,则为真。 这用于确定空元组是否是有效表达式。
- 参数
简化 (bool) –
with_condexpr (bool) –
extra_end_rules (可选[元组[str, ...]]) –
explicit_parentheses (bool) –
- 返回类型
联合[jinja2.nodes.Tuple, jinja2.nodes.Expr]
- class jinja2.lexer.TokenStream(generator, name, filename)
令牌流是产生 令牌 的可迭代对象。 然而,解析器不会对其进行迭代,而是调用
next()
以前进一个标记。 当前活动令牌存储为 current。- 参数
generator (Iterable[jinja2.lexer.Token]) –
名称 (可选[str]) –
文件名 (可选[str]) –
- current
当前的 Token。
- __next__()
前进一个令牌并返回旧的。
使用内置的
next()
而不是直接调用它。- 返回类型
- property eos: bool
我们是在流的尽头吗?
- expect(expr)
期望给定的令牌类型并返回它。 这接受与 jinja2.lexer.Token.test() 相同的参数。
- 参数
expr (str) –
- 返回类型
- look()
看下一个令牌。
- 返回类型
- next_if(expr)
执行令牌测试并在匹配时返回令牌。 否则返回值为 None。
- 参数
expr (str) –
- 返回类型
- push(token)
将令牌推回流。
- 参数
token (jinja2.lexer.Token) –
- 返回类型
没有任何
- skip(n=1)
前面有 n 个代币。
- 参数
n (int) –
- 返回类型
没有任何
- skip_if(expr)
像 next_if() 但只返回 True 或 False。
- 参数
expr (str) –
- 返回类型
布尔值
- class jinja2.lexer.Token(lineno, type, value)
- 参数
lineno (int) –
type (str) –
值 (str) –
- lineno
令牌的行号
- type
令牌的类型。 这个字符串是实习的,因此您可以使用
is
运算符将其与任意字符串进行比较。
- value
代币的价值。
- test(expr)
针对令牌表达式测试令牌。 这可以是令牌类型或
'token_type:token_value'
。 这只能针对字符串值和类型进行测试。- 参数
expr (str) –
- 返回类型
布尔值
- test_any(*iterable)
针对多个令牌表达式进行测试。
- 参数
iterable (str) –
- 返回类型
布尔值
lexer 模块中还有一个实用函数,可以计算字符串中的换行符:
- jinja2.lexer.count_newlines(value)
- 计算字符串中换行符的数量。 这对于过滤流的扩展很有用。
- 参数
- 值 (str) –
- 返回类型
- 整数
AST
AST(抽象语法树)用于表示解析后的模板。 它是节点的构建,然后编译器将其转换为可执行的 Python 代码对象。 提供自定义语句的扩展可以返回节点以执行自定义 Python 代码。
下面的列表描述了当前可用的所有节点。 AST 可能会在 Jinja 版本之间发生变化,但会保持向后兼容。
有关更多信息,请查看 jinja2.Environment.parse() 的代表。
- exception jinja2.nodes.Impossible
- 如果节点无法执行请求的操作,则引发。