如何在 Jinja2 自定义过滤器中使用 Python 生成器
Posted
技术标签:
【中文标题】如何在 Jinja2 自定义过滤器中使用 Python 生成器【英文标题】:How to use Python Generator in Jinja2 Custom Filter 【发布时间】:2020-07-19 00:10:35 【问题描述】:我需要生成一个带有字母索引的文档,比如这个:
Channels:
- A: Foobar item
- B: Foobaz item
- ...
我有带有Foobar
、Foobaz
等的输入文件,我希望jinja2
从模板文件中使用索引A
、B
等生成它,如下所示:
Channels: % for item in items %
- None | next_id : item.name item % endfor %
我想用这个模板使用 Python Generator,但是我找不到可行的解决方案,最新的代码版本是:
...
# Simple letters generator
def idgen():
value = 'A'
while True:
yield value
value = (chr(ord(value)+1))
gen = idgen()
# Function to be used as Custom Filter
# https://jinja.palletsprojects.com/en/master/api/#writing-filters
# I don't know is it implementable without function, just with generator
def next_id():
return next(gen)
env = Environment(loader=FileSystemLoader(template_dir))
env.filters['next_id'] = next_id
template = env.get_template(template_filename)
# items = ['name': 'Foobar', 'name': 'Foobaz']
print(next_id()) # To see if generator iterates
print(template.render(items=items))
print(next_id())
对应的输出是:
B
Channels:
- A: Foobar item
- A: Foobaz item
C
需要你的帮助,蜂群。
【问题讨论】:
我需要在模板 None | next_id
中发送None
,因为 Jinja API 需要它。这是添加包装函数的两个原因之一。
【参考方案1】:
到目前为止,我只找到了一种解决方法。假设 Jinja 根据自定义过滤器的功能输入使用某种缓存/优化:
这里:
B
Channels:
- A: Foobar item
- A: Foobaz item
C
所以最明显的解决方法是每次都发送新的输入,例如 loop.index | next_id
:
模板:
Channels: % for item in items %
- loop.index | next_id : item.name item % endfor %
结果:
Channels:
- A: Foobar item
- B: Foobaz item
【讨论】:
以上是关于如何在 Jinja2 自定义过滤器中使用 Python 生成器的主要内容,如果未能解决你的问题,请参考以下文章