Jinja2:本地/全局变量

时间:2013-07-29 13:42:34

标签: flask jinja2

{% set disabled = '' %}
{% for voter in record.voters %}
    {% if user == voter %}
        {% set disabled = 'disabled' %}
    {% endif %}
    {{ disabled }}  # outputs: 'disabled'
{% endfor %}
{{ disabled }}  # outputs: ''

我在Jinja2中有这个模板。 我需要的是'禁用'变量在外面可见'对于'环。 这可能吗?

5 个答案:

答案 0 :(得分:11)

处理此问题的最简单方法是移动将disabled变量设置为视图函数的逻辑,并将其发送到准备使用的模板。将应用程序逻辑与表示混合不是一个好主意,模板应该尽可能地接收数据。

也就是说,有一个丑陋的黑客可以使你想要的东西成为可能,显示在this question的公认答案中。

该解决方案涉及为Jinja2启用do扩展并使用它来修改全局数组。要启用扩展程序,请使用:

app.jinja_env.add_extension('jinja2.ext.do')

以下是适用于您的示例的解决方案:

{% set disabled = [] %}
{% for voter in record.voters %}
    {% if user == voter %}
        {% do disabled.append(1) %}
    {% endif %}
{% endfor %}
{% if disabled %}
    disabled
{% endif %}

答案 1 :(得分:9)

你可以像Miguel建议的那样使用数组/字典,但你本身不需要do扩展;你可以设置一个虚拟变量。我使用以下内容:

{% set glob={} %}

在顶部,然后在我的代码中:

{% set _ = glob.update({'disabled':True}) %}

_变量只是一个假人,之后你不会使用它。

答案 2 :(得分:2)

从2.10版开始,可以使用允许跨范围传播更改的名称空间对象来处理更复杂的用例:

{% set ns = namespace(found=false) %}
{% for item in items %}
    {% if item.check_something() %}
        {% set ns.found = true %}
    {% endif %}
    * {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}

答案 3 :(得分:0)

默认情况下,块可能无法访问外部作用域中的变量,您可以使用scoped修饰符覆盖它,如下所示:

{% for item in list scoped %}
{% endfor %}

请参阅:http://jinja.pocoo.org/docs/templates/#block-nesting-and-scope

答案 4 :(得分:0)

我意识到我正在回答旧话。但是,我最近开始使用Jinja并遇到了类似的问题:我需要计算嵌套周期中打印行的数量。我的解决方案是将一个计数器变量包装在一个类中,并将一个实例传递给模板。同样,您可以使用包装类,如此

class VoterStatus(object):
    def __init__(self, status='active'):
        self._status = status

    def set_disabled(self):
        self._status = 'disabled'

    def __str__(self):
        return self._status

相应地修改模板

{% for voter in record.voters %}
    {% if user == voter %}
        {% status.set_disabled() %}
    {% endif %}
    {{ status }}  # outputs: 'disabled'
{% endfor %}

将Status类实例传递给模板进行渲染:

tmplt.render(status=VoterStatus(), ...)

......鲍勃是你的叔叔。