Can a Jinja variable expand in an internal block?

I have the following Jinja template:

{% set mybool = False %} {% for thing in things %} <div class='indent1'> <ul> {% if current_user %} {% if current_user.username == thing['created_by']['username'] %} {% set mybool = True %} <li>mybool: {{ mybool }}</li> <!-- prints True --> <li><a href='#'>Edit</a></li> {% endif %} {% endif %} <li>Flag</li> </ul> </div> <hr /> {% endfor %} {% if not mybool %} <!-- always prints this --> <p>mybool is false!</p> {% else %} <p>mybool is true!</p> {% endif %} 

If the condition is met in a for loop, I would like to change mybool to true so that I can display mybool is true! below. However, it seems that the scope of the internal mybool limited by the if , so the desired mybool never installed.

How can I set the "global" mybool so that I can use it in the last if ?

EDIT

I found some suggestions (only cached pages were viewed correctly), but they don't seem to work. Perhaps they are deprecated in Jinja2 ...

EDIT

The solution is given below. I'm still wondering why the above suggestions do not work. Does anyone know for sure that they are out of date?

+56
variables scope templates jinja2
Feb 02 2018-11-02T00:
source share
8 answers

One way to limit this restriction is to enable the extension of the "do" expression and use an array instead of boolean:

 {% set exists = [] %} {% for i in range(5) %} {% if True %} {% do exists.append(1) %} {% endif %} {% endfor %} {% if exists %} <!-- exists is true --> {% endif %} 

To enable the Jinja "do" expression expression extension: e = jinja2.Environment(extensions=["jinja2.ext.do",])

+47
Feb 02 '11 at 22:00
source share
β€” -

Answer the question related to this: I wanted to have a global counter for the number of times when I entered a certain if pattern in the pattern, and in the end it turned out lower.

At the top of the template:

 {% set counter = ['1'] %} 

In the if block, I want to count:

 {% if counter.append('1') %}{% endif %} 

When displaying the invoice:

 {{ counter|length }} 

String '1' can be replaced with any string or number, I suppose. This is still a hack, but not very big.

+15
Mar 06 '14 at 18:56
source share

You can solve your problem using this hack (without extensions):

 import jinja2 env = jinja2.Environment() print env.from_string(""" {% set mybool = [False] %} {% for thing in things %} <div class='indent1'> <ul> {% if current_user %} {% if current_user.username == thing['created_by']['username'] %} {% set _ = mybool.append(not mybool.pop()) %} <li>mybool: {{ mybool[0] }}</li> <!-- prints True --> <li><a href='#'>Edit</a></li> {% endif %} {% endif %} <li>Flag</li> </ul> </div> <hr /> {% endfor %} {% if not mybool[0] %} <!-- always prints this --> <p>mybool is false!</p> {% else %} <p>mybool is true!</p> {% endif %} """).render(current_user={'username':'me'},things=[{'created_by':{'username':'me'}},{'created_by':{'username':'you'}}]) 
+8
Feb 18 '14 at 16:57
source share

Update 2018

Starting with Jinja 2.10 (November 8, 2017), a namespace() object exists to solve this particular problem. See the official assignment documentation for more details and an example; class documentation then illustrates how to assign multiple values ​​to a namespace.

+8
May 13 '18 at 2:08
source share

When writing contextfunction() or something similar, you may have noticed that the context is trying to stop you from changing it.

If you manage to change the context using the internal context API, you may have noticed that the changes in the context do not look visible in the template. The reason for this is because Jinja only uses context as the primary data source for template variables for performance reasons.

If you want to change the context, write a function that returns a variable in its place, which you can assign to a variable using set:

{% set comments = get_latest_comments() %}

Source

+4
05 Oct '11 at 12:53
source share

It is required to find the maximum number of records in an object (object) from the list (objects_from_db),

This does not work for reasons known in jinja2 and the scope variable.

  {% set maxlength = 0 %} {% for object in objects_from_db %} {% set ilen = object.entries | length %} {% if maxlength < ilen %} {% set maxlength = ilen %} {% endif %} {% endfor %} 

Here is what works:

  {% set mlength = [0]%} {% for object in objects_from_db %} {% set ilen = object.entries | length %} {% if mlength[0] < ilen %} {% set _ = mlength.pop() %} {% set _ = mlength.append(ilen)%} {% endif %} {% endfor %} {% set maxlength = mlength[0] %} 

Hope this helps someone else try to understand the same thing.

+3
Mar 19 '17 at 15:22
source share

Found this wonderful article that describes a small hack. It is not possible to change the value of the jinja variable in another area, but you can change the values ​​of the global dictionary:

 # works because dictionary pointer cannot change, but entries can {% set users = ['alice','bob','eve'] %} {% set foundUser = { 'flag': False } %} initial-check-on-global-foundUser: cmd.run: name: echo initial foundUser = {{foundUser.flag}} {% for user in users %} {%- if user == "bob" %} {%- if foundUser.update({'flag':True}) %}{%- endif %} {%- endif %} echo-for-{{user}}: cmd.run: name: echo my name is {{user}}, has bob been found? {{foundUser.flag}} {% endfor %} final-check-on-global-foundUser: cmd.run: name: echo final foundUser = {{foundUser.flag}} 

I also found this syntax very useful for setting a value without actually using set :

 {%- if foundUser.update({'flag':True}) %}{%- endif %} 

In fact, he checks the result of the update operation on the dictionary (a note to himself).

0
Aug 29 '18 at 13:35
source share

This is a common case for anyone who wants to use the namespace() object so that the variable is stored outside the for loop.

 {% set accumulator = namespace(total=0) %} {% for i in range(0,3) %} {% set accumulator.total = i + accumulator.total %} {{accumulator.total}} {% endfor %}' {# 0 1 3 #} {{accumulator.total}} {# 3 (accumulator.total persisted past the end of the loop) #} 
0
Sep 07 '19 at 16:27
source share



All Articles