Django查询两次返回相同的对象

时间:2014-04-09 10:47:36

标签: mysql django filter duplicates

通用示例。当我做这样的查询时

a = MyObject.objects.filter(...)

a将包含过滤器匹配的所有内容。当我这样做时:

a.filter(...)

a只包含与两个过滤器匹配的对象,对吗?所以在第一个filter()之后,我可能有5个元素,然后在第二个filter()之后我可能有5个剩下的2个?

我的一个查询得到了奇怪的结果。以下查询:

>>> Item.objects.filter(account__in=Account.objects.filter(customer=a), disabled=False)
[<Item: PSN-100396>]

这产生了一个结果。请记住,100396是主键,因此只有一个具有此idnetifier的Item。现在,当我应用一个额外的过滤器时,该过滤器应仅显示已禁用的发票上的项目或没有发票:

>>> Item.objects.filter(account__in=Account.objects.filter(customer=a), disabled=False).filter(Q(iteminv__invoice__disabled=False) | Q(iteminv__isnull=True))
[<Item: PSN-100396>, <Item: PSN-100396>]

我用同一个对象得到这个结果两次......这怎么可能?我误解了什么吗?

将所有内容放在一个filter()中会产生相同的奇怪输出:

>>> Item.objects.filter(Q(account__in=Account.objects.filter(customer=a)), Q(disabled=False), Q(iteminv__invoice__disabled=False) | Q(iteminv__isnull=True))
[<Item: PSN-100396>, <Item: PSN-100396>]

Django版本1.6.2

1 个答案:

答案 0 :(得分:13)

由于在多对多关系上进行过滤时所涉及的连接或反向外键关系实例在结果集中可能出现两次(在这种情况下,Django将主要应用INNER JOIN,这可能会产生重复)。因此,您应该在查询集上使用distinct()。 (sql查询中的联接使Item出现在表中,表示它与Account的每个关系。)

另见the examples in the django documentation过滤多对多关系。

编辑:如果您想使用SQL /和/或检查生成的查询,请执行print Item.objects.filter(your_query).query之类的操作。