Generating dynamic strings in jinja2

Viewed 1071

In jinja2, I want to generate strings that enumerate things, different fruits in this example. I have the following template file. Note the line with "Fruit_str not set" is there fore debugging purposes.

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    {% set fruit_str = "Fruit_str not set" %}
    {% for fruit in fruits %}
        {% if loop.first %}
            {% set fruit_str = fruit %}
        {% elif loop.last %}
            {% set fruit_str = fruit_str + " and " + fruit + "." %}
        {% else %}
            {% set fruit_str = fruit_str + ", " + fruit %}
        {% endif %}
    {% endfor %}
    You have {{fruit_str}}
  </body>
</html>

which gets this JSON as input

{ "fruits" : ["apples", "oranges", "bananas", "pears"] }

The expected output would be

 You have apples, oranges, bananas and pears.

However, the actual output is

You have Fruit_str not set

This indicates that the loop isn't run at all. ´I have read the jinja2 documentation on loops (http://jinja.pocoo.org/docs/2.10/templates/), but I can't find what is wrong in this example. What is wrong here?

1 Answers

In Jinja2 a for loop have its own namespace; therefore the variables you set within the loop is local to the loop, and once outside the loop, the variable of the same name would revert to the one of the outer scope.

You can use the namespace object to get around this issue:

{% set ns = namespace(fruit_str="Fruit_str not set") %}
{% for fruit in fruits %}
    {% if loop.first %}
        {% set ns.fruit_str = fruit %}
    {% elif loop.last %}
        {% set ns.fruit_str = ns.fruit_str + " and " + fruit + "." %}
    {% else %}
        {% set ns.fruit_str = ns.fruit_str + ", " + fruit %}
    {% endif %}
{% endfor %}
You have {{ns.fruit_str}}

Please see the documentation of namespace for details.

Related