web-dev-qa-db-fra.com

Jinja2: changer la valeur d'une variable à l'intérieur d'une boucle

Je veux changer la valeur de la variable déclarée en dehors de la boucle dans une boucle. Mais en constante évolution, il conserve la valeur initiale en dehors de la boucle.

{% set foo = False %}

{% for item in items %}
  {% set foo = True %}
  {% if foo %} Ok(1)! {% endif %}
{% endfor %}

{% if foo %} Ok(2)! {% endif %}

Cela rend:

Ok(1)!

Donc, la seule (mauvaise) solution trouvée jusqu'à présent était la suivante:

{% set foo = [] %}

{% for item in items %}
  {% if foo.append(True) %} {% endif %}
  {% if foo %} Ok(1)! {% endif %}
{% endfor %}

{% if foo %} Ok(2)! {% endif %}

Cela rend:

Ok(1)!
Ok(2)!

Mais c'est très moche! Existe-t-il une autre solution plus élégante?

57
Shankar Cabus

Essayez également une approche basée sur un dictionnaire. Cela semble moins laid.

{% set vars = {'foo': False} %}

{% for item in items %}
  {% if vars.update({'foo': True}) %} {% endif %}
  {% if vars.foo %} Ok(1)! {% endif %}
{% endfor %}

{% if vars.foo %} Ok(2)! {% endif %}

Cela rend également:

Ok(1)!
Ok(2)!
57
Pashka

comme mentionné dans la documentation:

Veuillez noter que les affectations dans les boucles seront effacées à la fin de l'itération et ne pourront pas survivre à la portée de la boucle.

mais à partir de la version 2.10, vous pouvez utiliser des espaces de noms:

    {% set ns = namespace(foo=false) %}      
    {% for item in items %}
      {% set ns.foo = True %}
      {% if ns.foo %} Ok(1)! {% endif %}
    {% endfor %}

    {% if ns.foo %} Ok(2)! {% endif %}
22
Omer

Vous pouvez le faire pour nettoyer le code du modèle

{% for item in items %}
  {{ set_foo_is_true(local_vars) }}
  {% if local_vars.foo %} Ok(1)! {% endif %}
{% endfor %}
{% if local_vars.foo %} Ok(2)! {% endif %}

Et dans l'utilisation du code serveur

items = ['item1', 'item2', 'item3']
#---------------------------------------------
local_vars = { 'foo': False }
def set_foo_is_true(local_vars):
  local_vars['foo'] = True
  return ''
env.globals['set_foo_is_true'] = set_foo_is_true    
#---------------------------------------------
return env.get_template('template.html').render(items=items, local_vars=local_vars)

Cela pourrait être généralisé aux éléments suivants

{{ set_local_var(local_vars, "foo", False) }}
{% for item in items %}
  {{ set_local_var(local_vars, "foo", True) }}
  {% if local_vars.foo %} Ok(1)! {% endif %}
{% endfor %}
{% if local_vars.foo %} Ok(2)! {% endif %}

Et dans l'utilisation du code serveur

items = ['item1', 'item2', 'item3']
#---------------------------------------------
local_vars = { 'foo': False }
def set_local_var(local_vars, name, value):
  local_vars[name] = value
  return ''
env.globals['set_local_var'] = set_local_var
#---------------------------------------------
return env.get_template('template.html').render(items=items, local_vars=local_vars)
1
Daniel F