Python 如何在 Flask/Jinja 中选择/减少字典列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20529234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to select/reduce a list of dictionaries in Flask/Jinja
提问by No Surprises
I have a Jinja template with a list of dictionaries. Order matters. I'd like to reduce the list or lookup values based on the keys/values of the dictionaries. Here's an example:
我有一个包含字典列表的 Jinja 模板。订单很重要。我想根据字典的键/值减少列表或查找值。下面是一个例子:
{%
set ordered_dicts = [
{
'id': 'foo',
'name': 'My name is Foo'
},
{
'id': 'bar',
'name': 'My name is Bar'
}
]
%}
If I have a variable some_id = 'foo', how do I get 'My name is Foo'out of ordered_dictsin my Jinja template?
如果我有一个变量some_id = 'foo',我如何'My name is Foo'退出ordered_dicts我的 Jinja 模板?
I tried select()and selectattr()but couldn't figure them out based on the documentation. Here's what I tried:
我尝试过select(),selectattr()但无法根据文档弄清楚它们。这是我尝试过的:
{{ ordered_dicts|selectattr("id", "foo") }}
That outputs:
输出:
<generator object _select_or_reject at 0x10748d870>
I don't think I'm understanding the use of select()and selectattr()properly.
我认为我没有正确理解select()and 的selectattr()使用。
Do I need to iterate over the list and do the lookup manually?
我是否需要遍历列表并手动查找?
Update:
更新:
As codegeek and gipi pointed out, I need to do something like this with the generator:
正如 codegeek 和 gipi 指出的那样,我需要用生成器做这样的事情:
{{ ordered_dicts|selectattr("id", "foo")|list }}
The resulting error: TemplateRuntimeError: no test named 'foo', which clarifies how selectattr()works. The second argument has to be one of the builtin tests. As far as I can tell, none of these tests will let me check whether the value associated with a key matches another value. Here's what I'd like to do:
由此产生的错误:TemplateRuntimeError: no test named 'foo',它阐明了如何selectattr()工作。第二个参数必须是内置测试之一。据我所知,这些测试都不会让我检查与键关联的值是否与另一个值匹配。这是我想要做的:
{{ ordered_dicts|selectattr("id", "sameas", "foo")|list }}
But that doesn't work, since the sameastest checks whether two objects are really the same object in memory, not whether two strings/numbers are equivalent.
但这不起作用,因为sameas测试检查两个对象是否真的是内存中的同一个对象,而不是两个字符串/数字是否相等。
So is it possible to pick an item based on a key/value comparison test?
那么是否可以根据键/值比较测试来选择一个项目?
采纳答案by artvolk
I've just backported equaltolike this:
我刚刚equalto像这样反向移植:
app.jinja_env.tests['equalto'] = lambda value, other : value == other
After that this example from 2.8 docsworks:
之后这个来自 2.8 文档的例子有效:
{{ users|selectattr("email", "equalto", "[email protected]") }}
Update: Flask has a decorator for registering tests, slightly cleaner syntax: http://flask.pocoo.org/docs/api/#flask.Flask.template_test
更新:Flask 有一个用于注册测试的装饰器,语法更简洁:http: //flask.pocoo.org/docs/api/#flask.Flask.template_test
回答by gipi
select()and selectattr()act upon a listand return a list, so if you know that there is only one result take the first from the generator, i.e
select()并对 aselectattr()采取行动list并返回 a list,因此如果您知道只有一个结果,则从生成器中获取第一个结果,即
{{ oredered_dicts|selectattr("id", "foo")|first }}
{{ oredered_dicts|selectattr("id", "foo")|first }}
Note:code not tested
注意:代码未测试
回答by lawicko
It looks like the equaltofilter is coming in Jinja2.8 (changelog) but it doesn't have any release date set yet (24 Feb 2014). As a workaround I'd suggest using groupbyfilter:
看起来equalto过滤器即将出现在 Jinja2.8 ( changelog) 中,但它还没有设置任何发布日期(2014 年 2 月 24 日)。作为一种解决方法,我建议使用groupby过滤器:
<ul>
{% for group in persons|groupby('gender') %}
<li>{{ group.grouper }}<ul>
{% for person in group.list %}
<li>{{ person.first_name }} {{ person.last_name }}</li>
{% endfor %}</ul></li>
{% endfor %}
</ul>
回答by Michael Wyraz
Have a look to https://github.com/ansible/ansible/issues/8836for this issue.
有关此问题,请查看https://github.com/ansible/ansible/issues/8836。
A solution/workaround is to create a file filter_plugins/core.py in your workbook directory with the following content:
解决方案/变通方法是在您的工作簿目录中创建一个文件 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
}
And use it so:
并使用它:
{{ ordered_dicts|byattr("id", "foo") }}
回答by Sergey GRIZZLY
More natural way for Ansible is to create /etc/ansible/test_plugins/custom.py with content
Ansible 更自然的方法是使用内容创建 /etc/ansible/test_plugins/custom.py
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible import errors
def equalto(value, other):
return bool(value == other)
class TestModule(object):
''' Ansible file jinja2 tests '''
def tests(self):
return {
'equalto' : equalto,
}
回答by Aikude
For people who don't have selectattr (e.g. you're stuck with Jinja2.6), and don't want to make yet another custom filter, these 2 lines will solve your problem real quick.
对于没有 selectattr 的人(例如,您坚持使用 Jinja2.6),并且不想制作另一个自定义过滤器,这两行将很快解决您的问题。
{% set selection = [] %}
{% for x in biglist if x.criteria == 'pickme' %}{% do selection.append(x) %}{% endfor %}

