veryxcit
veryxcit

Reputation: 419

Jinja2 nested loop counter

{% set cnt = 0 %}
{% for room in rooms %}
  {% for bed in room %}
    {% set cnt = cnt + 1 %}
  {% endfor %}
{{ cnt }}
{% endfor %}

Say we have that nested loop, printed cnt will ALWAYS be 0, because that's what it was defined when we entered the 1st for loop. When we increment the counter in the inner loop, it seems to only be a local variable for the inner loop -- so it will increment while inside the loop, but then that local cnt is gone. HOW can we modify the global cnt???

As great as the Jinja2 doc may be, they are unclear about set variable scopes. The only thing mentioning scope was the "scoped" modifier for inner blocks, but I guess it can't be applied to everything ... crazy.

Upvotes: 18

Views: 24676

Answers (4)

Leonardo
Leonardo

Reputation: 1891

I find the official trick pointed out by @Pyglouthon in his answer to be by far the best solution. I'll just paste it here so people don't have to browse the comments to find the working link.

From the official docs: Accessing the parent Loop

<table>
{% for row in table %}
  <tr>
  {% set rowloop = loop %}
  {% for cell in row %}
    <td id="cell-{{ rowloop.index }}-{{ loop.index }}">{{ cell }}</td>
  {% endfor %}
  </tr>
{% endfor %}
</table>

Upvotes: 1

Chris Warth
Chris Warth

Reputation: 938

Scoping rules prevent you from accessing a variable declared outside a loop from inside the loop

To quote Peter Hollingsworth from his previous answer,

You can defeat this behavior by using an object rather than a scalar for 'cnt':

{% set cnt = [0] %}
{% for room in rooms %}
  {% for bed in room %}
    {% if cnt.append(cnt.pop() + 1) %}{% endif %} 
  {% endfor %}
{{ cnt[0] }}
{% endfor %}
total times through = {{ cnt[0] }}

Upvotes: 23

Oliver Fawcett
Oliver Fawcett

Reputation: 581

A very hacky way I recall using in the past:

{% set cnt = 0 %}
{% for room in rooms %}
    {% for bed in room %}
        {% if cnt += 1 %}
    {% endfor %}
{{ cnt }}
{% endfor %}

Not tested.

Upvotes: -3

Pyglouthon
Pyglouthon

Reputation: 552

For each loop, there is a loop object generated which have an index attribute.

http://jinja.pocoo.org/docs/dev/templates/#for

To access parent loop index, you can do like this: http://jinja.pocoo.org/docs/dev/tricks/#accessing-the-parent-loop

Or you could use enumerate which work the same in Jinja as in Python https://docs.python.org/2/library/functions.html#enumerate

Upvotes: 8

Related Questions