逻辑或 Django 多对多查询返回重复结果
Posted
技术标签:
【中文标题】逻辑或 Django 多对多查询返回重复结果【英文标题】:Logical or of Django many to many queries returns duplicate results 【发布时间】:2011-12-06 02:57:03 【问题描述】:我有这样的多对多关系模型:
class Contact(models.Model):
name = models.TextField()
address = models.TextField()
class Mail(models.Model):
to = models.ManyToManyField(Contact, related_name='received_mails')
cc = models.ManyToManyField(Contact, related_name='cced_mails')
我想获取给定电子邮件的收件人字段或抄送字段中的一组联系人。让我们试试吧:
>>> Contact.objects.filter(received_mails__id=111)
[<Contact: fred@foo.com>]
>>> Contact.objects.filter(cced_mails__id=111)
[<Contact: joe@bar.com>]
到目前为止一切顺利。每个关系我们都有一个联系人。但是将它们都放入同一个查询集中会很好。
>>> Contact.objects.filter(Q(received_mails__id=111) | Q(cced_mails__id=111))
[<Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, '...(remaining elements truncated)...']
发生了什么?我有一种感觉,这与在 SQL 中连接表有关,但我真的不明白在多对多关系的背后发生了什么。可能是我想做的事情很愚蠢,或者有一种简单的方法可以做到。不管怎样,我很高兴能走上正确的道路。
编辑:这是 QuerySet 的查询:
SELECT `mailshareapp_contact`.`id`, `mailshareapp_contact`.`name`,
`mailshareapp_contact`.`address` FROM `mailshareapp_contact`
LEFT OUTER JOIN `mailshareapp_mail_to`
ON (`mailshareapp_contact`.`id` = `mailshareapp_mail_to`.`contact_id`)
LEFT OUTER JOIN `mailshareapp_mail_cc`
ON (`mailshareapp_contact`.`id` = `mailshareapp_mail_cc`.`contact_id`)
WHERE (`mailshareapp_mail_to`.`mail_id` = 111
OR `mailshareapp_mail_cc`.`mail_id` = 111 )
【问题讨论】:
【参考方案1】:由于 SQL 返回所有匹配的记录,Django 尽职尽责地将它们映射到对象。您正在寻找的是 .distinct()
queryset 方法,该方法使 SQL 将所有重复的行合并为一个。
【讨论】:
成功了,谢谢。 (抱歉,我还不能投票给你。)这会通过使用 SELECT DISTINCT 而不仅仅是 SELECT 来更改查询。我不明白没有它你怎么能得到这么多个重复,但我的直接问题已经解决了。 对于满足至少一个 JOIN 和一个 WHERE 的mailshareapp_contact
× (mailshareapp_mail_to
+ NULL
) × (mailshareapp_mail_cc
+ NULL
) 的每个组合,您将获得一个单独的行条款。顺便说一句,如果以上回答了您的问题,您可以随时将其标记为已接受的回复。以上是关于逻辑或 Django 多对多查询返回重复结果的主要内容,如果未能解决你的问题,请参考以下文章
如何在双连接关系之后在 Django 中执行查询(或:如何绕过 Django 对多对多“通过”模型的限制?)