12

How can I sort a dict like

my_dict = {
    'abc': {'name': 'B', 'is_sth': True},
    'xyz': {'name': 'A', 'is_sth': True}
}

by name in Jinja?

I've tried {% for id, data in my_dict|dictsort(by='value') if data.is_sth %} but doesn't work as I expect.

eyettea
  • 1,376
  • 2
  • 16
  • 35
mvidalgarcia
  • 538
  • 1
  • 5
  • 14

3 Answers3

27

Solution:

my_dict.items()|sort(attribute='1.name')

mvidalgarcia
  • 538
  • 1
  • 5
  • 14
  • 2
    Some explanation would help, I understand "name" but what does the "1." relate to? – Ed Randall Sep 09 '19 at 15:29
  • 5
    `.items()` returns a tuple of two elements: key and value. `1` relates to the 2nd element i.e. the value and `.name` relates to the key from the internal dict. – mvidalgarcia Sep 18 '19 at 12:51
  • this answer proposes you don't need the 'items()' call: https://stackoverflow.com/a/5490174/1518225 – Stefan Feb 14 '20 at 13:17
  • So i understand i can reference in this way any inner key, does not matter the complexity of nesting ? like 1.name.x.y.z ? – nix-power Jun 14 '23 at 10:28
5

jinja2 has a perfect solution for it

do_dictsort(value, case_sensitive=False, by='key')

{% for item in mydict|dictsort %}
    sort the dict by key, case insensitive

{% for item in mydict|dicsort(true) %}
    sort the dict by key, case sensitive

{% for item in mydict|dictsort(false, 'value') %}
    sort the dict by key, case insensitive, sorted
    normally and ordered by value.
mrkiril
  • 821
  • 12
  • 11
0

if you can live with ordering your data outside jinja and then just displaying it, you could do this:

from jinja2 import Template
from collections import OrderedDict

tmplt = Template('''
{% for id, data in od.items() if data.is_sth %}
{{id}}, {{data}}
{% endfor %}
''')

od = OrderedDict((key, value) for key, value in
                 sorted(my_dict.items(), key=lambda x: x[1]['name']))

print(tmplt.render(od = od))

which gives:

xyz, {'name': 'A', 'is_sth': True}

abc, {'name': 'B', 'is_sth': True}

other than that you'd probably have to create a custom filter.

hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
  • That would work, but I would rather to order it in jinja. Actually I think I've found a solution: `{% for id, data in my_dict.items()|sort(attribute='1.name') if data.is_sth %}` – mvidalgarcia Apr 21 '17 at 12:22
  • @mvidalgarcia ha! i was trying something along those lines but did not the the quotes around `'1.name'` right... you can post what you found here as an answer yourself! (but only 24h after the question if i remember correctly). good luck! (so it's `my_dict.items()|sort(attribute='1.name')`, right?) – hiro protagonist Apr 21 '17 at 12:29
  • oh, sorry about the last question; you had the jinja statement in your comment already... – hiro protagonist Apr 21 '17 at 13:48