【问题标题】:Advanced queryset sort ordering - won't order as I would like高级查询集排序排序 - 不会按我的意愿排序
【发布时间】:2020-01-11 07:10:06
【问题描述】:

我正在尝试让查询集以特定方式排序,但不知道该怎么做。

首先,我希望它按降序排列 end_date - 任何空的 end_date 记录首先分组。

那么列表应该按primary字段排序,然后是降序amount

queryset = MyModel.exclude_denied.filter(user=user).order_by(
        "end_date", "primary", "-amount"
    )

这是我目前拥有的,但它并没有像我想要的那样返回它。

我希望组显示如下:

  • 没有end_date的项目

    • primary 项目首先列出,然后按 desc 排序 amount
  • 带有end_date的项目

    • primary 项目首先列出,然后按 desc 排序 amount

我正在尝试实现这样的查询集:

ItemA - end_date:None - primary:True
ItemB - end_date:None - primary:False
ItemC - end_date:None - primary:False
ItemD - end_date:08/10/2018 - primary:True
ItemE - end_date:07/10/2019 - Primary:False
ItemF - end_date:06/08/2018 - Primary:False
ItemG - end_date:04/16/2017 - Primary:False

是否尝试仅使用 order_by 适当的方法创建此订单?我觉得它很接近 - 但不完全在那里。

我认为更好的方法是创建 2 个查询集,然后将它们合并在一起以保持它们的顺序。

类似这样的:

Queryset1 = 没有end_date 的项目,降序primary,然后降序amount

Queryset2 = 带有end_date(desc)的项目,降序primary,然后降序amount

合并两个 Queryset,但保持 Queryset1 项首先按顺序列出,然后 Queryset2 项按顺序列出。

虽然我不确定实现这一目标的最佳方法,但我认为这将是最好的解决方案。

我正在寻找有关如何完成此任务的建议。

【问题讨论】:

  • 您从未提及您最初的方法到底出了什么问题。是否是带有 null end_date 的对象出现故障?
  • 不清楚“with end_date”是否应该按 end_date 排序,首先似乎是,但是当你解释你想要什么时,它似乎不再那样了。是否有多个具有相同 end_date 的项目应按主要排序,数量它们已按 end_date 排序(和分组)?
  • @dirkgroten - 是的,可以有多个具有相同 end_date 的项目应该由 primary 排序,然后是 amount 它们已经排序/分组之后结束日期

标签: python django django-queryset


【解决方案1】:

你可以使用F() to sort null values,像这样:

queryset = MyModel.exclude_denied.filter(user=user).order_by(
    F("end_date").desc(nulls_first=True), 
    "primary", 
    "-amount"
)

更新

经过反复评论,重新阅读您的问题,我突然想到您并不想对end_date 进行排序,而只想对它是否是是否为空。可能有更好的方法将end_date is NULL 直接转换为布尔值,但我认为这应该可行:

from django.db.models import Count

queryset = MyModel.exclude_denied.filter(user=user).annotate(
    num_end_date=Count("end_date")
).order_by(
    "num_end_date",
    "primary", 
    "-amount"
)

【讨论】:

  • 很好的答案,但在 Django 1.11(可能更早)中已经出现了这种情况,尽管此示例没有记录在案。
  • 这些数据中的一些有可能以" " 作为结束日期,这会导致错误:'' value has an invalid date format ... 所以这种方法并不能完全让我到达那里。虽然它很接近,但我认为如果数据更干净一点,这将是一个好方法。
  • 我清理了数据 - 这有效 - 但是 - 如果一个元素被标记为 primary 但有一个较旧的 end_date,则此命令无法将 Primary 元素放在顶部组。
  • @dirkgroten:谢谢。我要关闭文档,因为我不记得在那之前是否存在
  • @Hanny:你最后的评论让我觉得你不想按顺序排序(end_dateprimary-amount)。也许您应该使用对象列表以及您希望它们出现的确切顺序来修改您的初始问题。
猜你喜欢
  • 2012-07-30
  • 2010-11-19
  • 1970-01-01
  • 2016-11-11
  • 2014-08-09
  • 1970-01-01
  • 2013-01-29
  • 2016-11-30
  • 1970-01-01
相关资源
最近更新 更多