【问题标题】:Ordering a Django QuerySet after slicing it切片后订购 Django QuerySet
【发布时间】:2016-01-02 18:34:33
【问题描述】:

Django docs 说:

...即使对未评估的 QuerySet 进行切片会返回另一个未评估的 QuerySet,但不允许进一步修改它(例如,添加更多过滤器或修改排序),因为这不能很好地转换为 SQL 并且它不会有明确的意思是。

从这里我认为它意味着做这样的事情:

q1 = Pizza.objects.all()[0:5]
q2 = q1.order_by(...)

不允许。我有两个问题:

  • 文档为什么这么说?我可以理解,也许它不能很好地转换为 SQL,但对我来说,“明确的含义”是您获得前 5 个比萨饼对象,然后按任何标准对它们进行排序。
  • 如果你这样做会发生什么?我已经做了一段时间了,代码是正确的(但速度很慢)。它实际上是反向执行的——对所有 Pizza 对象进行排序,然后得到前 5 个?

【问题讨论】:

    标签: python sql django orm


    【解决方案1】:

    当您编写 ORM 代码时,它实际上与 SQL 语法相对应。特别是,ORM 会产生错误的 SQL 语法。当然会导致错误。

    这是你的查询集:

    q1 = Pizza.objects.all()[0:5]
    q2 = q1.order_by(...)
    

    对应的SQL语法:

    SELECT * FROM Pizza limit 5 order by your_column
    

    所以这是一个明显的错误。

    代码如何纠正 ORM?根据您的要求,我建议您这样做:

    q1 = Pizza.objects.all()[0:5]
    q2 = q1.sorted(q1, key=lambda x: x.your_column)
    

    它会返回你所期望的。


    我建议你在slice之前使用order by,如下所示:

    q1 = Pizza.objects.all().order_by(...)[0:5]
    

    【讨论】:

    • 请注意,这个解决方案的重点是它在 Python 中进行排序。像这里一样,只有几件物品时没关系。
    • ^^ order_by() 的工作原理是告诉数据库如何对结果集进行排序..您要的是前 5 条记录..但是如果您有前 5 条记录,您怎么知道没有指定顺序?您应该在切片之前订购该集合,以便知道您将获得哪些记录。
    猜你喜欢
    • 2011-05-13
    • 2014-06-20
    • 2021-05-23
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多