多对多字段上的 order_by 导致查询集中的重复条目
Posted
技术标签:
【中文标题】多对多字段上的 order_by 导致查询集中的重复条目【英文标题】:order_by on Many-to-Many field results in duplicate entries in queryset 【发布时间】:2014-06-29 07:12:13 【问题描述】:我正在尝试基于 m2m 字段执行 order_by,但它最终会在我的查询集中创建重复的条目。我一直在搜索有关堆栈交换的 django 文档和相关问题,但我无法提出任何解决方案。
型号:
class WorkOrder(models.Model):
...
appointment = models.ManyToManyField(Appointment, null=True, blank=True, related_name = 'appointment_from_schedule')
...
class Appointment(models.Model):
title = models.CharField(max_length=1000, blank=True)
allDay = models.BooleanField(default=False)
start = models.DateTimeField()
end = models.DateTimeField(null=True, blank=True)
url = models.URLField(blank=True, null=True)
查询:
qs = WorkOrder.objects.filter(work_order_status="complete").order_by("-appointment__start")
结果:
[<WorkOrder: 45: Davis>, <WorkOrder: 45: Davis>]
在交互模式下:
>>>qs[0] == a[1]
True
>>>qs[0].pk
45
>>>qs[1].pk
45
如果我删除 order_by,那么我只会得到一个结果,但稍后添加它会将重复的条目重新放入。
>>>qs = WorkOrder.objects.filter(work_order_status="complete")
>>>qs
[<WorkOrder: 45: Davis>]
>>>qs.order_by('appointment__start')
[<WorkOrder: 45: Davis>, <WorkOrder: 45: Davis>]
我试过添加.distinct()和.distinct('pk'),但是前者没有效果,后者导致报错:
ProgrammingError: SELECT DISTINCT ON expressions must match initial ORDER BY expressions
【问题讨论】:
【参考方案1】:您可以尝试将annotate
与values
一起使用:
qs = WorkOrder.objects.filter(work_order_status="complete").values("appointment").annotate(status="work_order_status").order_by("-appointment__start")
【讨论】:
我以前没有使用过注释,但是按照您的示例使用它会导致错误:ValueError:注释'work_order_status'与模型上的字段冲突。我将查看有关注释的文档,看看是否有一种方法可以使用它而不是过滤器。感谢您的想法 您可能还需要将values
与annotate
结合使用...更新了我的答案以反映这一点
不幸的是仍然没有运气。这给了我 AttributeError: 'str' object has no attribute 'default_alias' 从阅读文档看来,我可能想注释一个包含约会.start 的列,然后我可以过滤和排序,但我没有也能够让语法为此工作。
抱歉,帮不上什么忙。您可以查看以下链接 distinct and order_by 和 the docs Good Luck :)
我非常感谢您的努力,即使这不能解决问题,它也给了我一些新的东西来学习和尝试。【参考方案2】:
我接受了 sfletche 提供的关于使用 annotate 的建议,并在 freenode.net irc 频道 #django 中讨论了这个问题。
用户 FunkyBob 和 jtiai 能够帮助我使其正常工作。
由于每个工作订单可以有很多预约,当我们要求它按预约订购时,它会为每个预约实例返回一行,因为它不知道我打算让它订购哪个预约。
from django.db.models import Max
WorkOrder.objects.annotate(max_date=Max('appointment__start')).filter(work_order_status="complete").order_by('max_date')
所以,我们走在正确的道路上,只是要让语法正确。
感谢 sfletche、FunkyBob 和 jtiai 的帮助。
【讨论】:
以上是关于多对多字段上的 order_by 导致查询集中的重复条目的主要内容,如果未能解决你的问题,请参考以下文章