如何在Flask/Jinj中选择/减少字典列表

2024-05-16 05:32:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个带有字典列表的Jinja模板。秩序很重要。我想根据字典的键/值减少列表或查找值。下面是一个例子:

{%
    set ordered_dicts = [
        {
            'id': 'foo',
            'name': 'My name is Foo'
        },
        {
            'id': 'bar',
            'name': 'My name is Bar'
        }
    ]
%}

如果我有一个变量some_id = 'foo',如何从Jinja模板中的ordered_dicts中获取'My name is Foo'

我试过^{}^{}但根据文档无法找出它们。我试过的是:

{{ ordered_dicts|selectattr("id", "foo") }}

其结果是:

<generator object _select_or_reject at 0x10748d870>

我认为我没有正确理解select()selectattr()的用法。

我需要遍历列表并手动进行查找吗?


更新:

正如codegeek和gipi所指出的,我需要对生成器做如下操作:

{{ ordered_dicts|selectattr("id", "foo")|list }}

由此产生的错误:TemplateRuntimeError: no test named 'foo',它说明了selectattr()是如何工作的。第二个参数必须是the builtin tests中的一个。据我所知,这些测试都不允许我检查与键关联的值是否与另一个值匹配。我想做的是:

{{ ordered_dicts|selectattr("id", "sameas", "foo")|list }}

但这不起作用,因为sameas测试检查内存中的两个对象是否真的是同一个对象,而不是两个字符串/数字是否相等。

那么,是否可以基于键/值比较测试来选择一个项?


Tags: name模板id列表字典fooismy
3条回答

对于那些没有selectattr的人(例如,你被Jinja2.6困住了),并且不想再制作另一个自定义过滤器,这两行代码将很快解决你的问题。

{% set selection = [] %}
{% for x in biglist if x.criteria == 'pickme' %}{% do selection.append(x) %}{% endfor %}

看看这个问题的https://github.com/ansible/ansible/issues/8836

解决方案/解决方法是在工作簿目录中创建包含以下内容的文件filter_plugins/core.py:

def filter_list(list, key, value):
    return filter(lambda t: t[key] == value, list)

class FilterModule(object):
    def filters(self):
        return {
            'byattr': filter_list
        }

使用它:

{{ ordered_dicts|byattr("id", "foo") }}

我刚刚像这样背着equalto

app.jinja_env.tests['equalto'] = lambda value, other : value == other

之后this example from 2.8 docs工作:

{{ users|selectattr("email", "equalto", "foo@bar.invalid") }}

Update:Flask有一个用于注册测试的decorator,稍微干净一点的语法:http://flask.pocoo.org/docs/api/#flask.Flask.template_test

相关问题 更多 >