Django复杂查询否定

时间:2013-01-28 20:15:38

标签: django django-queryset

我需要从查询集中排除一些结果。这样做的条件是,我想要排除belong_to特定对象列表的所有记录,但包括那些第二个值不是特定值的记录(即使记录属于其中一个排除的记录)

在SQL中,我想象这将是:

SELECT * FROM some_table WHERE NOT (belongs_to_id IN [1,2,3] AND NOT foo=bar)

我希望这可行:

qs.exclude(Q(belongs_to__id__in=[1,2,3]) & ~Q(foo=bar))

但是,当我在connection.queries中查看结果时,似乎django省略了~Q(foo=bar)部分。

作为参考,这将在纯Python中做同样的事情:

included_ids = qs.filter(foo=bar).values_list('id', flat=True)
excluded_ids = qs.filter(belongs_to__id__in=[1,2,3]).values_list('id', flat=True)
filtered_excluded_ids = [x for x in excluded_ids if not x in included_ids]
new_qs = qs.exclude(id__in=filtered_excluded_ids)

我想避免使用此解决方案,因为它会导致额外的不必要的查询。

1 个答案:

答案 0 :(得分:1)

鉴于Q的意外结果,我认为你应该使用extra

qs.extra(where=['NOT ("customer_customer"."belongs_to_id" IN [%s] AND NOT "customer_customer"."sales_rep_id" = %d)'%(','.join(your_list),bar)])

有时Django查询语法本身无法表达复杂的WHERE子句(它甚至可能依赖于db后端...),但正如我所说的那样,这很奇怪。

并且,如果其他任何内容失败(例如,如果您的查询会变得更加复杂),您可以转到raw