在Jinja 2中求列表元素的和

16 投票
4 回答
37549 浏览
提问于 2025-04-18 18:41

我在Jinja2中有一个列表,里面包含了一些字典,类似这样:

items = [{'name':'name1', 'points':5}, {'name':'name2', 'points':7}, 
 {'name':'name3', 'points':2}, {'name':'name4', 'points':11}]

我需要做的是计算所有points的总和,并且在后面某个地方打印出来。

目前我得到的是:

{% set points = 0 -%}
{% for single_item in items -%}
    {% set points = points + single_item["points"] -%}
    {{points}}
{% endfor %}
{{ points }}

结果是:5 12 14 25 0

有没有办法让我在循环外获取到points的值25(循环中的最后一个值)呢?

4 个回答

-1

找到的内容来自:https://linuxtut.com/en/129012d5539a8724556d/

解决方案二:使用命名空间
<2019/12/21: 来自 na90ya> 似乎在使用 jinja2 2.10 版本引入的命名空间对象时,变量会被保留。(参考资料 [1])

count_test3.j2

{%- set ns = namespace(cnt=1) -%}
{%- for i in range(3) -%}
{%- set ns.cnt = ns.cnt + 1 -%}
{{ ns.cnt }}
{% endfor -%}
result : {{ ns.cnt }}

不过我还没试过这个...

4

这种逻辑通常应该放在控制器里,而不是模板中(也就是把逻辑和展示分开)。你需要先处理好数据,然后把每个项目和总数传递给模板:

from jinja2 import Template

template = Template(open('index.html').read())

items = [{'name': 'name1', 'points': 5},
         {'name': 'name2', 'points': 7},
         {'name': 'name3', 'points': 2},
         {'name': 'name4', 'points': 11}]

total = sum([i['points'] for i in items])

print template.render(items=items, total=total)

index.html:

<table>

{% for item in items %}
  <tr>
    <td>{{ item.name }}</td>
    <td>{{ item.points }}</td>
  </tr>
{% endfor %}

</table>

<strong>Total:</strong>{{ total }}

关于表达式 sum([i['points'] for i in items]) 的详细信息,可以查看 列表推导式

52

Jinja2 有一个叫做 sum 的过滤器,可以帮你完成这个任务:

{{ items | sum(attribute='points') }}

你可以在这里查看相关文档: https://jinja.palletsprojects.com/templates/#jinja-filters.sum

3

我已经成功让它工作了,虽然这个解决方案不是特别优雅,但确实能用:

{% set points = [0] -%}
{% for single_item in items -%}
    {% if points.append(points.pop()+ single_item["points"]) -%}{% endif %}
{% endfor %}
{{ points }}

points 将是一个只有一个元素的数组,这个元素就是总和。

也可以使用包含的do扩展,这样就可以替代{% if %}那一行了。

撰写回答