Jinja2: 更改循环中变量的值

我想改变循环中循环外部声明的变量的值。但是总是在变化,它将初始值保留在循环之外。

{% set foo = False %}


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


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

这表明:

Ok(1)!

因此,到目前为止,唯一(糟糕)的解决办法是:

{% set foo = [] %}


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


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

这表明:

Ok(1)!
Ok(2)!

但是,它是非常丑陋的! 还有其他更优雅的解决方案吗?

96664 次浏览

You could do this to clean up the template code

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

And in the server code use

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)

This could be generalized to the following

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

And in the server code use

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)

Try also dictionary-based approach. It seems to be less ugly.

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

This also renders:

Ok(1)!
Ok(2)!

as mentioned in the documentation:

Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope.

but as of version 2.10 you can use namespaces:

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