2012-02-28 22 views
44

Quiero cambiar el valor de la variable declarada fuera del bucle dentro de un bucle. Pero siempre cambiando, mantiene el valor inicial fuera del ciclo.Jinja2: Cambia el valor de una variable dentro de un bucle

{% set foo = False %} 

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

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

Esto hace:

Ok(1)! 

Así que la única solución de (mala) han encontrado hasta el momento era la siguiente:

{% set foo = [] %} 

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

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

Esto hace:

Ok(1)! 
Ok(2)! 

Pero, ¡es muy feo! ¿Hay alguna otra solución más elegante?

+3

No creo que hay alguna otra manera. Tal vez podrías reestructurar el código para que no necesites configurar la variable. –

+0

+1 para la pregunta, ya que se convirtió en respuesta para mí :) –

+0

@Shankar Cabus: gran pregunta. Esto probablemente debería clasificarse en 'Jinja Annoyances' – dreftymac

Respuesta

47

Pruebe también el enfoque basado en el diccionario. Parece ser menos feo

{% 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 %} 

Esto también hace que:

Ok(1)! 
Ok(2)! 
+2

Todavía feo, pero funciona. Estoy bastante sorprendido de que no haya una manera Pythonic de hacer esto con jinja2. – kramer65

+0

Definitivamente un poco más limpio, especialmente si necesita más de una variable –

+1

TLDR, ¿'set vars' simplemente no funciona en un bucle for? – ThorSummoner

1

Se podría hacer esto para limpiar el código de la plantilla

{% 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 %} 

Y en el uso de códigos del servidor

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) 

Esto podría generalizarse a la siguiente

{{ 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 %} 

Y en el código de servidor usa

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) 
4

como se menciona en la documentación:

Tenga en cuenta que las asignaciones en los bucles se borrará al final de la iteración y no pueden sobrevivir a la alcance del bucle

pero a partir de la versión 2.10 se pueden utilizar espacios de nombres:

{% 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 %} 
Cuestiones relacionadas