关于ManyToMany过滤和组合查询集的非常奇怪的行为
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于ManyToMany过滤和组合查询集的非常奇怪的行为相关的知识,希望对你有一定的参考价值。
日历有一个所有者,并有一个ManyToMany
字段'助手'我有一个日历谁有2个助手,其中一个是其所有者。我认为django shell中的这三行代码可以很好地解释奇怪的行为。
In [17]: Calendar.objects.filter(assistants=customer).exclude(owner=customer)
Out[17]: <QuerySet []>
In [20]: Calendar.objects.filter(owner=customer)
Out[20]: <QuerySet [<Calendar: aliz cal>, <Calendar: yassi has a calendar>]>
In [19]: Calendar.objects.filter(owner=customer) | Calendar.objects.filter(assistants=customer).exclude(owner=customer)
Out[19]: <QuerySet [<Calendar: aliz cal>, <Calendar: aliz cal>, <Calendar: yassi has a calendar>]>
当然,期望queryset join的结果是它们的实际并集。
答案
假设这是django 1.11+:
|
不代表工会。它表示两个查询集的OR组合(维护所有连接;因此aliz显示两次)。
qs1.filter(x=1) | qs2.exclude(x=1)
翻译为:
SELECT STUFF FROM TABLES_AND_JOINS WHERE (x = 1 OR NOT (x = 1))
而qs1.filter(x=1).union(qs2.exclude(x=1))
翻译为:
SELECT STUFF FROM TABLE1 WHERE x = 1 UNION SELECT STUFF FROM TABLE2 WHERE NOT x = 1
使用str(qs.query)
查看SQL。
另一答案
你正在做的是OR
- 两个查询的WHERE
子句,它们与union不同(并且在涉及加入时有点棘手;这里,ORM从查询集#1中的内部联接切换到查询集中的外部联接#3用于说明没有连接的第二个查询。请参阅相关的docs。
尝试从Django 1.11起提供的union()
:
qs1 = Calendar.objects.filter(assistants=customer).exclude(owner=customer)
qs2 = Calendar.objects.filter(owner=customer)
qs3 = qs1.union(qs2)
以上是关于关于ManyToMany过滤和组合查询集的非常奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate:@ManyToMany 关系中对象集的传递持久性