我想循环一个对象列表并计算满足要求的对象数量。我将我的代码基于我发现的其他示例,但它不起作用,循环后计数始终为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 %}
答案 0 :(得分:3)
对于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语法无法做到这一点。
为了在迭代中跟踪count
,您需要执行hacky-ish解决方法。设置一个列表,附加到它,然后计算它的长度。
{% 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 %}
答案 1 :(得分:2)
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 :(得分:0)
对于Jinja&lt; = 2.8,您显示的代码确实有效。然而,这是由于Jinja的范围规则中的{{3}},其定义为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 %}