我想在jinja2中有一个自定义过滤器,如下所示:
{{ my_list|my_real_map_filter(lambda i: i.something.else)|some_other_filter }}
但是当我实现它时,我收到此错误:
TemplateSyntaxError: expected token ',', got 'i'
看来jinja2的语法不允许lambdas作为参数?有一些不错的解决方法吗?现在,我在python中创建lambda然后将其作为变量传递给模板,但我宁愿能够在模板中创建它。
不,你不能通过一般的Python表达式来过滤Jinja2模板
混淆来自jinja2模板在许多方面与Python语法类似,但您应将其视为具有完全独立语法的代码。
Jinja2有严格的规则,可以预期在模板的哪个部分,它通常不允许python代码,它期望精确类型的表达式,这是非常有限的。
这符合概念,表示和模型应分开,因此模板不允许太多逻辑。无论如何,与许多其他模板选项相比,Jinja2是非常允许的,并且在模板中允许相当多的逻辑。
我有一个解决方法,我正在排序一个dict对象:
registers = dict(
CMD = dict(
address = 0x00020,
name = 'command register'),
SR = dict(
address = 0x00010,
name = 'status register'),
)
我想循环遍历寄存器字典,但按地址排序。所以我需要一种按“地址”字段排序的方法。为此,我创建了一个自定义过滤器并将lambda表达式作为字符串传递,然后我使用Python的内置eval()来创建真正的lambda:
def my_dictsort(value, by='key', reverse = False):
if by == 'key':
sort_by = lambda x: x[0].lower() # assumes key is a str
elif by == 'value':
sort_by = lambda x: x[1]
else:
sort_by = eval(by) # assumes lambda string, you should error check
return sorted(value, key = sort_by, reverse = reverse)
使用此功能,您可以将其注入jinja2环境,如下所示:
env = jinja2.Environment(...)
env.filters['my_dictsort'] = my_dictsort
env.globals['lookup'] = lookup # queries a database, returns dict
然后从您的模板中调用它:
{% for key, value in lookup('registers') | my_dict_sort("lambda x:x[1]['address']") %}
{{"""\
static const unsigned int ADDR_{key} = 0x0{address:04X}; // {name}
""" | format(key = key, address = value['address'], name = value['name'])
}}
{% endfor %}
输出:
static const unsigned int ADDR_SR = 0x00010; // status register
static const unsigned int ADDR_CMD = 0x00020; // command register
因此,您可以将lambda作为字符串传递,但是您必须添加自定义过滤器才能执行此操作。