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

我在 Jinja2 中有那个模板。我需要的是“禁用”变量在“for”循环之外可见。那可能吗?

4

5 回答 5

14

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

也就是说,有一个丑陋的黑客可以使您想要的成为可能,如对此问题的接受答案所示。

该解决方案涉及启用doJinja2 的扩展并使用它来修改全局数组。要启用扩展,请使用:

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 %}
于 2013-07-30T03:12:37.680 回答
11

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

{% set glob={} %}

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

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

_ 变量只是一个虚拟变量,以后不要使用它。

于 2015-04-11T19:14:42.667 回答
5

从 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 }}
于 2020-04-21T11:20:56.180 回答
1

默认情况下,块可能不会从外部范围访问变量,您可以通过使用scoped修饰符来覆盖它,如下所示:

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

见:http: //jinja.pocoo.org/docs/templates/#block-nesting-and-scope

于 2013-07-29T14:17:26.153 回答
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(), ...)

...鲍勃是你的叔叔。

于 2017-03-01T08:26:51.050 回答