【问题标题】:Jinja2: local/global variableJinja2:局部/全局变量
【发布时间】:2013-07-29 13:42:34
【问题描述】:
{% set disabled = '' %}
{% for voter in record.voters %}
    {% if user == voter %}
        {% set disabled = 'disabled' %}
    {% endif %}
    {{ disabled }}  # outputs: 'disabled'
{% endfor %}
{{ disabled }}  # outputs: ''

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

【问题讨论】:

    标签: flask jinja2


    【解决方案1】:

    处理此问题的最简单方法是将设置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 %}
    

    【讨论】:

    • 谢谢。我已经修改了我的代码,并按照你最初的建议做了。
    【解决方案2】:

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

    {% set glob={} %}
    

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

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

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

    【讨论】:

    • 完美,有点老套,但这就是我所需要的 ?
    【解决方案3】:

    从 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 }}
    

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

      • @c00p3r.web 在这种情况下,我建议为 jinja2 打开一个问题,因为这似乎是需要的功能:github.com/mitsuhiko/jinja2/issues
      • 这是一个很好的解决方案,遗憾的是它只适用于嵌套块/循环。
      【解决方案5】:

      我意识到我正在回答一个旧线程。然而,我最近开始使用 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(), ...)
      

      ...鲍勃是你的叔叔。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-24
        • 2017-11-08
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多