Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Jinja variable's scope extend beyond in an inner 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 the for loop, I'd like to change mybool to true so I can display mybool is true! below. However, it looks like the scope of the inner mybool is limited to the if statement, so the desired mybool is never set.

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

EDIT

I've found some suggestions (only the cached page views correctly), but they don't seem to work. Perhaps they're deprecated in Jinja2...

EDIT

Solution provided below. I am still curious why the suggestions above do not work though. Does anyone know for sure that they were deprecated?

like image 899
Matt Norris Avatar asked Feb 02 '11 02:02

Matt Norris


3 Answers

One way around this limitation is to enable the "do" expression-statement extension 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 Jinja's "do" expression-statement extension: e = jinja2.Environment(extensions=["jinja2.ext.do",])

like image 81
Garrett Avatar answered Oct 21 '22 07:10

Garrett


Answer to a related question: I wanted to have a global counter of the number of times I entered a certain if-block in the template, and ended up with the below.

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 count:

{{ counter|length }}

The string '1' can be replaced with any string or digit, I believe. It is still a hack, but not a very large one.

like image 25
Godsmith Avatar answered Oct 21 '22 07:10

Godsmith


Update 2018

As of Jinja 2.10 (8th Nov 2017) there is a namespace() object to address this particular problem. See the official Assignments documentation for more details and an example; the class documentation then illustrates how to assign several values to a namespace.

like image 16
Jens Avatar answered Oct 21 '22 07:10

Jens