如何编写“连接器” Jinja2 的扩展?
您好,我一直在尝试为 jinja2 创建一个扩展,它将使用分隔符连接多个项目,同时跳过计算结果为空格的项目(模板片段)。
这些片段有几个,您永远不知道哪些片段将是非空的,哪些片段将是非空的。
听起来像是一项微不足道的任务,但我真的很难让它在 jinja2 中工作。也许部分原因是 jinja 不允许定义自定义模板节点。
您有什么建议吗?下面是一个将完成解析工作的片段,但它缺少评估部分。
class JoinerExtension(Extension):
"""Template tag that joins non-whitespace (string) items
with a specified separator
Usage syntax:
{% joinitems separator='|' %}
....
{% separator %}
....
{% separator %}
....
{% endjoinitems %}
where value of "separator" within the joinitems tag
can be an expression, not necessarily a sting
"""
tags = set(['joinitems'])
def parse(self, parser):
"""parse function for the
joinitems template tag
"""
lineno = next(parser.stream).lineno
#1) read separator
separator = None
while parser.stream.current.type != 'block_end':
name = parser.stream.expect('name')
if name.value != 'separator':
parser.fail('found %r, "separator" expected' %
name.value, name.lineno,
exc=TemplateAssertionError)
# expressions
if parser.stream.current.type == 'assign':
next(parser.stream)
separator = parser.parse_expression()
else:
var = parser.stream.current
parser.fail('assignment expected after the separator' %
var.value, var.lineno,
exc=TemplateAssertionError)
#2) read the items
items = list()
end_tags = ['name:separator', 'name:endjoinitems']
while True:
item = parser.parse_statements(end_tags)
items.append(item)
if parser.stream.current.test('name:separator'):
next(parser.stream)
else:
next(parser.stream)
break
Hi I've been trying to create an extension for jinja2 that would join multiple items with a separator, while skipping items (template fragments) that evaluate to whitespace.
There are several of those fragments and you never know in advance which ones will be non-empty and which ones will.
Sounds like a trivial task, but I had real hard time making this to work in jinja2. Maybe part of the reason is that jinja does not allow to define custom template nodes.
Would you have any suggestions? Below is a snippet that will do the parsing job, but it's missing the evaluation part.
class JoinerExtension(Extension):
"""Template tag that joins non-whitespace (string) items
with a specified separator
Usage syntax:
{% joinitems separator='|' %}
....
{% separator %}
....
{% separator %}
....
{% endjoinitems %}
where value of "separator" within the joinitems tag
can be an expression, not necessarily a sting
"""
tags = set(['joinitems'])
def parse(self, parser):
"""parse function for the
joinitems template tag
"""
lineno = next(parser.stream).lineno
#1) read separator
separator = None
while parser.stream.current.type != 'block_end':
name = parser.stream.expect('name')
if name.value != 'separator':
parser.fail('found %r, "separator" expected' %
name.value, name.lineno,
exc=TemplateAssertionError)
# expressions
if parser.stream.current.type == 'assign':
next(parser.stream)
separator = parser.parse_expression()
else:
var = parser.stream.current
parser.fail('assignment expected after the separator' %
var.value, var.lineno,
exc=TemplateAssertionError)
#2) read the items
items = list()
end_tags = ['name:separator', 'name:endjoinitems']
while True:
item = parser.parse_statements(end_tags)
items.append(item)
if parser.stream.current.test('name:separator'):
next(parser.stream)
else:
next(parser.stream)
break
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
内置的 joiner 类可能有效吗?这是文档中的一个简单示例。
您提到提前不知道哪些片段将为空;也许可以在“显示”之前将每个片段的值存储在变量中,以便您可以确定哪些片段确实是空的。例如:
您甚至可以将上述模式封装在宏中以减少重复:
其中
print_if_notblank
是定义为的宏:Would the built-in joiner class potentially work? Here is a simple example from the documentation.
You mentioned that it is not known ahead of time which fragments will be empty; perhaps it is possible to store the value of each fragment in a variable before "displaying" it so that you can determine which fragments are indeed empty. For example:
You could even encapsulate the above pattern in a macro to reduce repetition:
where
print_if_notblank
is a macro defined as: