管道|
或与号&
结合实际的查询集OR
or AND
到 SQL 查询,所以它看起来像是组合在一起的。
one = Photo.objects.filter(id=1)
two = Photo.objects.filter(id=2)
combined = one | two
print(combined.query)
>>> ... WHERE ("photo_photo"."id" = 1 OR "photo_photo"."id" = 2)...
但是,当您组合更多过滤器并排除时,您可能会注意到它会给您带来奇怪的结果。这就是为什么当您比较计数时它不匹配的原因。
如果你使用.union()
您必须具有具有相同数据类型的相同列,因此您必须注释两个查询集。关于信息.union()
- .UNION() 中的 SELECT 语句必须具有相同的列数
- 这些列还必须具有相似的数据类型
- 每个 SELECT 语句中的列也必须具有相同的顺序
你必须记住,蟒蛇的论点kwargs
对于不定数量的参数是字典,因此如果要使用带有多个注释的注释,则无法确保列的正确顺序。幸运的是,您可以通过链接注释命令来解决这个问题。
# printed query of this won't be consistent
photo_queryset.annotate(label_count=Count('labels'), tag_count=Count('tags'))
# this will always have same order of columns
photo_queryset.annotate(label_count=Count('labels')).annotate(tag_count=Count('tags'))
然后你可以使用.union()
并且它不会弄乱注释的结果。还.union()
应该是最后一个方法,因为之后.union()
你不能使用filter
类似的方法。如果你想保留重复项,你可以使用.union(qs, all=True)
since .union()
有默认值all=False
并打电话DISTINCT
在查询集上
photos = Photo.objects.annotate(c=Count('labels'))
one = photos.exclude(c__lte=4)
two = photos.filter(painting=True)
all = one.union(two, all=True)
one.count() + two.count() == all.count()
>>> True
那么它应该像你所描述的那样工作