Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select/reduce a list of dictionaries in Flask/Jinja

Tags:

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:

{%
    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_dicts in my Jinja template?

I tried select() and selectattr() but couldn't figure them out based on the documentation. Here's what I tried:

{{ 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.

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:

{{ 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:

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

But that doesn't work, since the sameas test checks whether two objects are really the same object in memory, not whether two strings/numbers are equivalent.

So is it possible to pick an item based on a key/value comparison test?

like image 285
No Surprises Avatar asked Dec 11 '13 20:12

No Surprises


People also ask

How do you iterate through a dictionary in Jinja?

To iterate through a list of dictionaries in Jinja template with Python Flask, we use a for loop. to create the parent_list list of dicts. in our Jinja2 template to render the parent_list items in a for loop.

Do you have to use Jinja with flask?

Flask leverages Jinja2 as its template engine. You are obviously free to use a different template engine, but you still have to install Jinja2 to run Flask itself. This requirement is necessary to enable rich extensions.


2 Answers

I've just backported equalto like this:

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

After that this example from 2.8 docs works:

{{ 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

like image 66
artvolk Avatar answered Oct 23 '22 10:10

artvolk


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.

{% set selection = [] %}
{% for x in biglist if x.criteria == 'pickme' %}{% do selection.append(x) %}{% endfor %}
like image 27
Aikude Avatar answered Oct 23 '22 09:10

Aikude