如何创建jinja2扩展?

3 投票
1 回答
3899 浏览
提问于 2025-04-15 14:49

我在尝试为jinja2写一个扩展。我写了这样的代码:

http://dumpz.org/12996/

但是我遇到了一个错误:'NoneType' object is not iterable。这个问题出在哪里呢?应该返回parse。另外,_media应该接受什么,返回什么呢?

1 个回答

12

你正在使用一个 CallBlock,这表示你希望你的扩展作为一个块来工作。例如:

{% mytest arg1 arg2 %}
stuff
in
here
{% endmytest %}

nodes.CallBlock 需要你传入一个节点列表,这些节点代表了你扩展的主体部分(也就是里面的语句)。目前你传入的是 None,所以出现了错误。

一旦你解析了你的参数,就需要继续解析块的主体部分。幸运的是,这个过程很简单。你可以直接这样做:

body = parser.parse_statements(['name:endmytest'], drop_needle=True)  

然后返回一个新的节点。CallBlock 会接收一个要调用的方法(在这个例子中是 _mytestfunc),这个方法提供了你扩展的逻辑。

body = parser.parse_statements(['name:endmytest'], drop_needle=True)  
return nodes.CallBlock(self.call_method('_mytestfunc', args),[], [], body).set_lineno(lineno)

另外,如果你不想让你的扩展成为一个块标签,例如:

{% mytest arg1 arg2 %}

那么你就不应该使用 nodes.CallBlock,而是应该使用 nodes.Call,这个方法不需要主体参数。所以你只需要这样做:

return self.call_method('_mytestfunc', args)  

self.call_method 只是一个方便的包装函数,它为你创建一个 Call 节点。

我花了几天时间在写 Jinja2 扩展,这个过程很复杂。文档不多(除了代码本身)。Coffin 的 GitHub 项目有一些扩展的例子,你可以在 这里 找到。

撰写回答