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!
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
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With