【问题标题】:Django Template Slice - Reversing OrderDjango 模板切片 - 反转顺序
【发布时间】:2010-12-26 07:03:02
【问题描述】:

感谢另一个问题的非常有用的提示,我了解到我可以通过在模板中切片来限制列表中值的数量:

{% for comment in thread.comment_set.all|slice:":3" %}

现在我想获得我的 cmets 的最后 3 个结果,所以我想一个简单的 ":-3" 或 "-3" 就可以了,唉:

Caught an exception while rendering: Negative indexing is not supported.

同时使用:

{% for comment in thread.comment_set.all|slice:":3" reversed %}

没有效果,因为如果我有 5 个 cmets,而不是 1、2、3,它会按 3、2、1 的顺序显示前三个。

有什么方法可以在不进入我的数据库的情况下显示帖子的最后 3 个 cmets?我希望能够完全使用模板系统来做到这一点。

解决方案

{% for comment in thread.comment_set.all|dictsortreversed:"created"|slice:"3" %}

由于我的表具有创建的时间戳,因此显示最后三个。

【问题讨论】:

  • 如果您希望项目按时间顺序(而不是逆时间顺序)显示:{% for comment in thread.comment_set.all|dictsortreversed:"created"|slice:"3" reversed %}

标签: python django django-templates


【解决方案1】:

我认为,我只需要这个并制定了一个更完整的解决方案。希望人们觉得它有用。视图需要找到last inserted record (example here) 的id。您必须颠倒顺序并获取最后输入的最新记录的 id (PK),这现在将成为第一条记录,现在很容易在堆顶部找到 ;-)。计算您想要的下限 id 值,然后在末尾使用此运算符从较低到最新或最后一个条目进行排序 ...[n:m] (我认为这只是一个列表运算符),删除不需要的记录,然后按正常顺序呈现。对于 django 表示例,这是我的代码:

def showLatestRels(request):
    #This view shows the latest 15 entries in the Release table
    LastInserted = Release.objects.order_by('-pk')[0]
    UpperLimit = LastInserted.id
    LowerLimit = UpperLimit - 15
    RelTable = Release.objects.all()
    tablevalslat = ReleaseTable(RelTable[LowerLimit:UpperLimit])
    RequestConfig(request).configure(tablevalslat)
    return render(request, 'DCESrtap/latrels.html', {'tablevalslat': tablevalslat}

)

方法很多,见Django docs Make/limit Queries
但无法让 dictsort 的想法发挥作用....

【讨论】:

    【解决方案2】:

    如果查询集已经按“created”排序,您可以反转查询集。所以这里有一个更快的解决方案。

    {% for comment in thread.comment_set.all.reverse|slice:":3" %}
    

    如果你不想倒序排列。

    {% for comment in thread.comment_set.all.reverse|slice:":3"|dictsort:"created" %}
    

    尽管您应该遵循上述 Jarrets Hardie 的建议,并在视图中而不是在模板中执行所有这些逻辑。

    【讨论】:

      【解决方案3】:

      使用 Comment 类的 Meta 类的“ordering”属性来设置所需的元素排序。

      IMO 模板不适合订购数据集。应在模型或视图中进行排序。

      【讨论】:

        【解决方案4】:

        您不能在将列表传递给模板之前对其进行切片吗?

        【讨论】:

          【解决方案5】:

          Django 的数据库查询是惰性求值的,所以thread.comment_set.all 的结果是一个QuerySet,而不是一个列表。 QuerySet 支持许多类似列表的函数,但不支持负切片,因此索引错误不是来自模板过滤器本身。 (如果您很好奇,QuerySet 对象上的切片会被转换为 SQL 语句中的 limit 子句,这就是您不能使用负数的原因。

          一般来说,Django 鼓励模板和模型的严格解耦; views.py 模块是您进行任何需要数据库模型和查询集方法知识以将模型数据转换为模板的简单变量和结构的工作的粘合剂。

          从模板对模型运行相关查询并不是您通常在 Django 模板中看到的,这是有充分理由的。现在,从comment_set 中分割最后三个元素似乎很简单。但请记住,数据库不会以任何保证的顺序返回结果。这意味着,除了您的切片之外,您现在还需要添加一个 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:" %}
          

          【讨论】:

          • 我喜欢我得到和修改的答案是我实际上是在拉我的线程表,然后从模板中拉各个 cmets,所以 Django 正在做拉正确 cmets 的工作。我会说我不太在意这样一个事实,即它只提取每条评论只是为了将它们全部切片保存 3,它确实工作得很好,因为它把它们全部提取出来,我按它们的创建日期对它们进行排序,然后将它们切片.
          • 如果有一个我可以编写的查询将拉 X 线程和它们各自的 last 三个 cmets,我会很高兴。相反,我这样做。
          • 如果可以的话,我会给你所有的 +1 :-/ 15 Rep :(
          【解决方案6】:

          我没有看到 dictsortreversed 过滤器经常使用,根据文档,它需要一个键来排序

          {% for comment in thread.comment_set.all|dictsortreversed:"name"|slice:"3" %}
          

          【讨论】:

            猜你喜欢
            • 2013-04-30
            • 2017-04-24
            • 2013-05-08
            • 2012-02-08
            • 2014-06-18
            • 2011-07-04
            • 2013-08-04
            • 2018-12-24
            • 1970-01-01
            相关资源
            最近更新 更多