【问题标题】:How to reverse a for loop in a Django template and then slice the result如何在 Django 模板中反转 for 循环,然后对结果进行切片
【发布时间】:2016-05-02 08:03:51
【问题描述】:

在 Django 模板中,我正在遍历一组照片,并一张一张地显示它们。具体来说,现在我只有一张照片集,包含 6 个对象。我这样显示这 6 个对象:

{% for pic in picstream.photo_set.all reversed %}
    <img src="{{ pic.image_file.url }}"></img>
{% endfor %}

在语句中添加reversed 可以让我获得所需顺序的 6 个对象(即最新的 ID 在前)。

接下来,我想显示不超过 4 个来自 photo_set 的对象。我将|slice:":4" 添加到picstream.photo_set.all 以实现此目的。问题是,它正在从我想要的排序中切断前两个对象

似乎应该有一种方法可以将列表首先反转,然后稍后进行切片?需要一种简单的方法来做到这一点,而不会影响性能。

【问题讨论】:

  • 模板系统是为了表达演示,而不是程序逻辑。
  • 如果 slice 确实支持所有语法,那么您可以使用类似:|slice:"::-1"|slice:":4",它首先反转查询集,然后进入前 4。但我不确定这是否是一个好习惯甚至关于它的效率。
  • 这不属于您的模板。虽然 |slice':4' 将导致在数据库端进行限制 4 查询,因为 QuerySet 对象在 Django 中是惰性求值的,如果列表反转将触发完整的查询而没有限制,然后在 python 中切片一个潜在的大结果集,从而对不必要的数据库和应用服务器。
  • @KárolyNagy:处理这种情况的最佳建议是什么?包括一个说明性的例子并将其写成答案会有所帮助。我想要最好的方法来做到这一点,并且会接受提供的答案。

标签: django django-templates


【解决方案1】:

您可以使用查询集本身的reverse 方法,而不是为for 模板标签使用reversed 参数:

{% for pic in picstream.photo_set.all.reverse|slice:":4" %}
    <img src="{{ pic.image_file.url }}"></img>
{% endfor %}

如果您在代码中的其他位置评估原始(非反转)查询集,那么这将导致第二个查询访问数据库。如果是这种情况,那么最好将逻辑移动到视图代码本身或模板标记中。

【讨论】:

  • 请注意,对于使用reverse,必须已经在查询集或模型本身上定义了一些排序,否则它不会有任何影响。检查最后一段here
  • 是的,确实如此。我假设在模型/查询集级别定义了一些默认排序,否则 OP 不会有兴趣反转它:-)。此外,即使没有......它仍然可以工作......只是顺序是任意的。
猜你喜欢
  • 2021-06-30
  • 2021-03-28
  • 1970-01-01
  • 2010-12-26
  • 2022-01-25
  • 2021-04-01
  • 2010-09-21
  • 2012-06-27
  • 1970-01-01
相关资源
最近更新 更多