Reputation: 848
{% set disabled = '' %}
{% for voter in record.voters %}
{% if user == voter %}
{% set disabled = 'disabled' %}
{% endif %}
{{ disabled }} # outputs: 'disabled'
{% endfor %}
{{ disabled }} # outputs: ''
I have that template in Jinja2. What I need is 'disabled' variable to be visible outside 'for' loop. Is that possible?
Upvotes: 14
Views: 42473
Reputation: 357
As of version 2.10 more complex use cases can be handled using namespace objects which allow propagating of changes across scopes:
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
Upvotes: 7
Reputation: 1
I realise I'm answering to an old thread. However, I started using Jinja recently and ran into a similar problem: I needed to count the amount of printed rows in nested cycles. My solution was wrapping a counter variable in a class and passing an instance to the template. Similarly, you can use a wrapper class, like so
class VoterStatus(object):
def __init__(self, status='active'):
self._status = status
def set_disabled(self):
self._status = 'disabled'
def __str__(self):
return self._status
Modify your template accordingly
{% for voter in record.voters %}
{% if user == voter %}
{% status.set_disabled() %}
{% endif %}
{{ status }} # outputs: 'disabled'
{% endfor %}
Pass a Status class instance to the template for rendering:
tmplt.render(status=VoterStatus(), ...)
...and Bob's your uncle.
Upvotes: 0
Reputation: 397
You can use an array/dict like Miguel suggests, but you do not need the do extension per se; you can set a dummy var. I use the following:
{% set glob={} %}
at the top, and then in my code:
{% set _ = glob.update({'disabled':True}) %}
The _ variables is just a dummy, you don't use it afterwards.
Upvotes: 15
Reputation: 67502
The easiest way to handle this is to move the logic that sets the disabled
variable to your view function and send it down to the template ready to be used. Mixing application logic with presentation is not a good idea, templates should receive the data as digested as possible.
That said, there is an ugly hack that makes what you want possible, shown in the accepted answer to this question.
The solution involves enabling the do
extension for Jinja2 and using it to modify a global array. To enable the extension use:
app.jinja_env.add_extension('jinja2.ext.do')
Here is the solution adapted to your example:
{% set disabled = [] %}
{% for voter in record.voters %}
{% if user == voter %}
{% do disabled.append(1) %}
{% endif %}
{% endfor %}
{% if disabled %}
disabled
{% endif %}
Upvotes: 16
Reputation: 2970
By default blocks may not access variables from outer scopes, you can override this by using the scoped
modifier like so:
{% for item in list scoped %}
{% endfor %}
See: http://jinja.pocoo.org/docs/templates/#block-nesting-and-scope
Upvotes: 1