Reputation: 4312
How can I break out of a for loop in jinja2?
my code is like this:
<a href="#">
{% for page in pages if page.tags['foo'] == bar %}
{{page.title}}
{% break %}
{% endfor %}
</a>
I have more than one page that has this condition and I want to end the loop, once the condition has been met.
Upvotes: 62
Views: 116280
Reputation: 923
{% set break = False %}
{% for item in items %}
{% if not break %}
{% if item.name == 'target' %}
{# do action before break #}
{% set break = True %}
{% endif %}
{% endif %}
{% endif %}
this is considered literally make the native jinja2 break that can added in any example of jinja2 not just specific case with check, no topic answer provided the way to make break statement for jinja2 they answer with code example to this question and if i used their code to make a break in jinja2 copy paste will not work as this answer is not how make break , it how break this case only thats why i added my answer, all you need usually is replace the item.name == 'target'
with your condition or just break the first, my target with way like the native way to add break jinja2 not just answer this quest if loop.index==1
what if i need break if db.row.id == 2 or other diffrent cases, then you need my example also it help not repeat all code as other solutions require repeat action on all if check and diffrent actions needed now u can just {% set break = True %} as it break keyword native that was my target when make this.
Upvotes: 1
Reputation: 11
I like to use something like this.
{% set ns = namespace(matched = 0) %}
{% for location in locations %}
{% for range in locations[location] %}
{% if range | network_in_usable( ansible_default_ipv4.address ) and not ns.matched == 1 %}
{% set ns.matched = 1 %}
{{ location }}
{% endif %}
{% endfor %}
{% endfor %}
Using a namespace variable we loop through until we find a match if variable = 0, as soon as we find a match, change the variable to 1 and your loop effectively stops.
I used to have another if statement at the bottom outside of the loop that then said if ns.matched == 0, print a default value . . . but I opted to remove that so that the ansible playbook could give a default value instead.
For anyone interested in the code above.. we use a template to lookup the location code based on the IP address.
So the variable:
{"locations": {"rno_openstack":["10.8.0.0/24"],"rno": ["10.8.0.0/14"]}}
You can see if we had 10.8.0.1 that we would return rno_openstack
but the loop will stop so that we don't also return rno
since the IP also falls in to that CIDR range.
and we call the template with
"{{ lookup('template', 'lookup_location.j2') | replace('\n', '') }}"
Upvotes: 0
Reputation: 1121416
You can't use break
, you'd filter instead. From the Jinja2 documentation on {% for %}
:
Unlike in Python it’s not possible to break or continue in a loop. You can however filter the sequence during iteration which allows you to skip items. The following example skips all the users which are hidden:
{% for user in users if not user.hidden %} <li>{{ user.username|e }}</li> {% endfor %}
In your case, however, you appear to only need the first element; just filter and pick the first:
{{ (pages|selectattr('tags.foo', 'eq', bar)|first).title }}
This filters the list using the selectattr()
filter, the result of which is passed to the first
filter.
The selectattr()
filter produces an iterator, so using first
here will only iterate over the input up to the first matching element, and no further.
Upvotes: 80
Reputation: 3164
Break and Continue can be added to Jinja2 using the loop controls extension. Jinja Loop Control Just add the extension to the jinja environment.
jinja_env = Environment(extensions=['jinja2.ext.loopcontrols'])
as per sb32134 comment
Upvotes: 27
Reputation: 550
But if you for some reason need a loop you can check the loop index inside for-loop block using "loop.first":
{% for dict in list_of_dict %}
{% for key, value in dict.items() if loop.first %}
<th>{{ key }}</th>
{% endfor %}
{% endfor %}
Upvotes: 13