Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jinja loop on nested list creates empty output

I have af list of this structure passed to the template with the name bars in Python 3.4:

[{'var': 1.18, 'occurrences': [0.0805, 0.0808, 0.0991, 0.0994, 0.2356], 'name': 'item name'},
 {'var': 2.31, 'occurrences': [1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791], 'name': 'other name'}]

I want it to create the following output for each dictionary:

% List with names
item 1: item name
item 2: other name

% List with vars
item 1: 1.18
item 2: 2.31

% List with occurences
item 1: 0.0805, 0.0808, 0.0991, 0.0994, 0.2356
item 2: 1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791

The first two are no problem, but I can't get it to loop the occurrence list. I use the following jinja template:

{% for item in bars %}
  item {{ loop.index }}: {{ item.name }}
{% endfor %}

{% for item in bars %}
  item {{ loop.index }}: {{ item.var }}
{% endfor %}

{% for item in bars recursive %}
  {% if item.occurrences %}
    Item {{ loop.index}}: {{ loop(item.occurrences) }}
  {% else %}
    No content
  {% endif %}
{% endfor %}

This gives this odd output in the third case:

Item 1:       No content
No content
No content
No content
No content

Item 2:       No content
No content
No content
No content
No content
No content

That is odd since it seems that it loops each item of the list with occurrences, but it does not pass the test for content. What am I doing wrong?

Edit: All three answers pointed me in the right direction, but @famousgarkin give the most elaborate and flexible answer. I ended up with the following solution:

{% for item in bars %} 
  Item {{ loop.index }}: {% for occurrence in item.occurrences %} subitem {{ loop.index }}: {{ occurrence }} {% endfor %}
{% endfor %}

This lets me enclose each item in separate context, which is what I want. But since this aim was not clear from the start, I wish I could upvote all your answers. Sorry, but thank you all for quick help!

like image 297
Stenskjaer Avatar asked Oct 20 '22 05:10

Stenskjaer


1 Answers

If you don't want to format the nested items using the exact same logic you don't use the recursion.

In your sample, when looping bars items, it goes to the correct path, since you can see Item n: on the output. Then it descends to a recursive call to process item.occurrences items. Now when it asks if occurrences exists it's actually asking for bar.occurrences[i].occurrences[j], which of course doesn't have the occurrences attribute and it goes the No content path. You can see it in action using the following:

{% for item in bars recursive %}
  {% if item.occurrences %}
    Item {{ loop.index }}: {{ loop(item.occurrences) }}
  {% else %}
    No content, {{ item.__class__ }}, {{ item }}
  {% endif %}
{% endfor %}

Yields:

Item 1: No content, <type 'float'>, 0.0805
No content, <type 'float'>, 0.0808
No content, <type 'float'>, 0.0991
No content, <type 'float'>, 0.0994
No content, <type 'float'>, 0.2356
...

It'll work like this, for example:

{% for item in bars %}
  {% if item.occurrences %}
    Item {{ loop.index }}: {{ item.occurrences }}
  {% else %}
    No content
  {% endif %}
{% endfor %}

Yields:

Item 1: [0.0805, 0.0808, 0.0991, 0.0994, 0.2356]
Item 2: [1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791]

If you want to iterate on the items yourself to provide your own formatting, you can for example use the Jinja join filter:

{% for item in bars %}
  {% if item.occurrences %}
    Item {{ loop.index }}: {{ item.occurrences|join(', ') }}
  {% else %}
    No content
  {% endif %}
{% endfor %}

Yields:

Item 1: 0.0805, 0.0808, 0.0991, 0.0994, 0.2356
Item 2: 1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791

Or loop again to roll entirely custom formatting:

{% for item in bars %}
  {% if item.occurrences %}
    Item {{ loop.index }}:
    {% for occurrence in item.occurrences %}
      {{ loop.index }}. {{ occurrence }}
    {% endfor %}
  {% else %}
    No content
  {% endif %}
{% endfor %}

Yields:

Item 1:
1. 0.0805
2. 0.0808
3. 0.0991
4. 0.0994
5. 0.2356
...
like image 92
famousgarkin Avatar answered Oct 22 '22 19:10

famousgarkin