Django 模板切片 - 反转顺序
感谢另一个问题给我的提示,我了解到可以通过在模板中切片来限制列表中的值数量,方法如下:
{% for comment in thread.comment_set.all|slice:":3" %}
现在我想获取我评论的最后三个结果,所以我想简单地用“:-3”或“-3”来实现,结果却不如我所愿:
Caught an exception while rendering: Negative indexing is not supported.
另外,使用:
{% for comment in thread.comment_set.all|slice:":3" reversed %}
也没有效果,因为如果我有5条评论,它显示的不是1、2、3,而是3、2、1的顺序。
有没有办法在不进入我的数据库的情况下显示一篇文章的最后三条评论?我希望能仅通过模板系统来做到这一点。
解决方案
{% for comment in thread.comment_set.all|dictsortreversed:"created"|slice:"3" %}
由于我的表中有创建时间戳,这样就能显示最后三条评论。
6 个回答
使用评论类(Comment class)中元类(Meta class)的“ordering”属性来设置元素的排序方式。
在我看来,模板(templates)并不是排序数据的合适地方。排序应该在模型(Models)或视图(Views)中进行。
我发现大家用 dictsortreversed 这个过滤器的机会不多,根据文档,它需要一个关键字来进行排序。
{% for comment in thread.comment_set.all|dictsortreversed:"name"|slice:"3" %}
Django的数据库查询是懒加载的,所以当你使用thread.comment_set.all
时,得到的是一个查询集(QuerySet),而不是一个列表。查询集支持很多类似列表的操作,但不支持负数切片,所以出现索引错误并不是因为模板过滤器本身的问题。(如果你感兴趣,查询集上的切片会被转换成SQL语句中的limit
子句,这就是为什么你不能使用负数的原因)。
一般来说,Django鼓励模板和模型之间保持严格的分离;views.py
模块就是用来把这两者连接起来的地方,你在这里进行任何需要了解数据库模型和查询集方法的工作,以便把模型数据转换成简单的变量和结构,供模板使用。
在模板中对模型进行相关查询并不是Django模板中常见的做法,这背后有很好的理由。现在,切割评论集中的最后三个元素看起来很简单,但请记住,数据库返回的结果没有保证的顺序。这意味着,除了你的切片操作之外,你还需要添加一个排序(order_by)子句;在模板中根本无法表达这一点,也不应该这样做。更好的想法是把视图看作是模型和模板之间的翻译,让这些与数据库相关的工作在视图中完成,而不是嵌入在HTML中。
在这种情况下,我建议你从视图中将一个有序的切片传递给模板:
# take first three sorted descending
comments = thread.comment_set.order_by('-something')[:3]
context = Context({'comments':comments})
return HttpResponse(tmplt.render(context))
如果你必须在模板中进行切片,并且你真的不在乎结果的排序,可以把一个列表传递给模板。slice
过滤器会很乐意进行负数切片:
comments = list(thread.comment_set.all())
context = Context('comments':comments)
在模板中:
{% for comment in comments|slice:"-3:" %}