首页 > 解决方案 > Django ORM“|” 操作员返回重复项

问题描述

假设我有一个看起来像这样的模型类:

class User:
    ...
    projects = models.ManyToManyField(Project, blank=True)
    subscribed_projects = models.ManyToManyField(Project, blank=True)

我有一些返回两个查询集内容的视图逻辑:

    return self.request.user.projects.all() | self.request.user.subscribed_projects.all()

在我的特定场景中,假设同一个项目不会同时出现在两者中。

以下是其中一位用户的当前关系:

>>> me = User.objects.get(id=1)
>>> me.projects.all()
<QuerySet [<Project: A>, <Project: B>, <Project: C>, <Project: D>, <Project: E>]>
>>> me.subscribed_projects.all()
<QuerySet [<Project: F>]>

这是我无法解释的部分:

>>> me.projects.all() | me.subscribed_projects.all()
<QuerySet [<Project: A>, <Project: B>, <Project: C>, <Project: D>, <Project: D>, <Project: E>, <Project: F>]>

项目“D”在这里出现了两次,即使它只出现在其中一个查询集中!

现在,我可以通过添加distinct()或使用union()来实现我想要的行为,但为什么会这样呢?

标签: pythondjangodjango-models

解决方案


projectssubscribed_projects是两个不同的多对多关系Project,因此当从它们查询一个时,存在与不同中间表的连接。虽然我不知道查询集__or__运算符的确切内部工作方式,但由于您没有收到错误,我只能假设它将使用组合查询中两个表的连接。

从上面的分析可以得出结论,你最终会连接多个表,因为很明显,多个表的连接很容易引入重复的结果。如您所知, usingdistinct可以为您解决此问题(不建议使用union,因为那样会限制您可以对联合查询进行的可能过滤器):

queryset = me.projects.all() | me.subscribed_projects.all()
queryset = queryset.distinct()

推荐阅读