【问题标题】:Setting variable in Jinja for loop doesn't persist between iterations在 Jinja for 循环中设置变量不会在迭代之间持续存在
【发布时间】:2017-10-25 18:35:04
【问题描述】:

我想遍历对象列表并计算有多少对象满足要求。我的代码基于我找到的其他示例,但它不起作用,循环后计数始终为 0。

对于每个房子,我想遍历每个房间并计算有多少房间有一张床。我想输出,然后重置下一个房子的计数。

{% for house in city %}
{% set count = 0 %}
    <div>{{ house.address }} has {{ count }} beds in it rooms.</div>
    {% for room in house %}
    {% if room.has_bed == True %}{% set count = count + 1 %}{% endif %}
   {% endfor %}
{% endfor %}

【问题讨论】:

    标签: python jinja2


    【解决方案1】:

    Jinja 2.10 引入了namespace 对象来处理循环中的赋值和比较。

    {% set ns = namespace(beds=0) %}
    {% for room in house %}
        {% if room.has_bed %}
            {% set ns.beds = ns.beds + 1 %}
        {% endif %}
    {% endfor %}
    {{ house.address }} has {{ ns.beds }} beds.
    

    通常,set 不处理属性,这就是为什么旧答案用方法改变对象的原因。 namespace 是特殊的,所以设置属性确实有效。

    原来的计数器不起作用的原因是 Jinja 的scope rules。与 Python 不同,大多数块都是新的作用域。 set 总是定义一个局部变量,除了 namespace.attribute 这个新的特殊情况。


    在这种特定情况下,您可以使用过滤器完成您想要的操作。

    {% set beds = house.rooms|selectattr('has_bed')|length %}
    {{ house.address }} has {{ beds }} beds.
    

    但是,在某些情况下需要跨范围存储信息。例如,如果您想在增加计数器的同时输出一些信息,那么使用namespace 是有意义的。

    【讨论】:

      【解决方案2】:

      对于 Jinja 2.9,范围行为已修复,使以前版本中的代码无效。 count 的增量值仅存在于循环范围内。 Their example涉及设置变量,但概念是一样的:

      请记住,不能在块内设置变量并让它们显示在块外。这也适用于循环。该规则的唯一例外是不引入范围的 if 语句。因此,以下模板不会像您预期的那样:

      {% set iterated = false %}
      {% for item in seq %}
          {{ item }}
          {% set iterated = true %}
      {% endfor %}
      {% if not iterated %} did not iterate {% endif %}
      

      Jinja 语法无法做到这一点。

      您需要做一个 hacky-ish 变通方法,以便在迭代中跟踪 count。设置一个列表,附加到它,然后计算它的长度。

      {% for house in city %}
          {% set room_count = [] %}
          {% for room in house %}
              {% if room.has_bed %}
                  {% if room_count.append(1) %}{% endif %}
              {% endif %}
          {% endfor %}
          <div>{{ house.address }} has {{ room_count|length }} beds.</div>
      {% endfor %}
      

      【讨论】:

        【解决方案3】:

        对于 Jinja incorrect behavior 导致的,该规则在 2.9 中已修复。

        {% for house in city %}
            {% set count = 0 %}
            {% for room in house %}
                {% if room.has_bed %}
                    {% set count = count + 1 %}
                {% endif %}
            {% endfor %}
            <div>{{ house.address }} has {{ count }} beds.</div>
        {% endfor %}
        

        【讨论】:

          猜你喜欢
          • 2012-03-15
          • 2023-03-08
          • 2022-01-23
          • 2021-01-21
          • 1970-01-01
          • 1970-01-01
          • 2019-01-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多