在包含之后编译Jinja2扩展

3 投票
1 回答
1078 浏览
提问于 2025-04-16 07:42

在Jinja2中,是否可以让一个Node在所有include语句执行完之后再渲染?

这是一个更大问题的关键解决方案的一部分。

示例代码:

x.py

from jinja2 import nodes, Environment, FileSystemLoader
from jinja2.ext import Extension

class XExtension(Extension):
    tags = set(['x', 'get_x'])

    def __init__(self, environment):
        super(XExtension, self).__init__(environment)
        environment.extend(
            x = 0,
        )

    def parse(self, parser):
        tag = parser.stream.next()
        return getattr(self, "_%s" % str(tag))(parser, tag)

   def _get_x(self, parser, tag):
        """ Return the output """
        return nodes.Const(self.environment.x)

   def _x(self, parser, tag):
        """ Add an x """
        self.environment.x += 1
        return nodes.Const('<!-- Adding an X -->')

env = Environment(
    loader      = FileSystemLoader('.'),
    extensions  = [XExtension],
    )

template = env.get_template('x.html')
print template.render()

x.html

Xx {% x %} Xx {% x %}
{% include "y.html" %}
Xs xes: {% get_x %}

y.html

Yx {% x %}
Ys xes: {% get_x %}

输出结果是

Xx <!-- Adding an X --> Xx <!-- Adding an X -->
Yx <!-- Adding an X -->
Ys xes:3
Xs xes 2

我想知道如何让Xs xes计算y.html中的X的数量,这正是我想要和期待的行为?

换句话说,有没有办法延迟解析或将x.html中的_get_x()返回的内容转化为文本?

非常感谢你的阅读。

祝好,

布莱恩

1 个回答

3

Jinja2可以逐步处理模板数据。模板会按照指令逐条执行,变成一串小字符串,最后通过render()方法把这些小字符串拼接成一个完整的unicode字符串。不过,你也可以通过调用generate()来获取这个字符串流,而不是使用render()

如果在流中加入一些信号并对其进行后处理,可能可以实现类似的功能,但这与Jinja2的设计初衷相悖,所以可能会出现严重的问题,并且完全没有支持。

撰写回答