Django在/不在查询中


100

我试图弄清楚如何在Django中编写“不在”风格的查询。例如,我正在考虑的查询结构将如下所示。

select table1.* 
from table1
where table1.id not in 
(
  select table2.key_to_table1
  from table2 
  where table2.id = some_parm 
)

假设模型名为table1和table2,django语法会是什么样?

Answers:


164
table1.objects.exclude(id__in=
    table2.objects.filter(your_condition).values_list('id', flat=True))

排除功能的作用类似于Not您要查询的运算符。该属性flat = True告诉table2查询以返回value_list一级列表。所以...最后,您IDs将从table2 中获得一个列表,您将用该列表来供用户定义中的条件table1,该条件将被exclude函数拒绝。


3
我也遇到了列表构造函数[table2 ...]-> list(table2 ...)为我工作的麻烦。
RickyA 2011年

3
修正:table1.objects.exclude(id__in = table2.objects.filter(your_condition).values_list('id',flat = True))
理查德(Richard

1
试图使用此解决方案并遇到问题,因此,如果其他任何人都遇到了此问题,Objs=Tbl1.objects.filter(...); IDs=Objs.values_list('id', flat=True); Objs.delete(); Tbl2.objects.filter(id__in=IDs')这将不起作用,因为ID实际上是QuerySet对象。当我删除它源自的行时,它不再与其他查询一起使用。解决方案是Tbl2.objects.filter(id__in=list(IDs))–将其转换为列表
Dakusan

1
根据上下文,如果过滤器就像“具有count(xx)== yy”,则使用速度要快100倍以上annotate()(timeit给了我1.0497902309998608和0.00514069400014705)
Olivier Pons,

10

使用这些模型:

class table1(models.Model):
    field1 = models.CharField(max_length=10)      # a dummy field

class table2(models.Model):
    key_to_table1 = models.ForeignKey(table1)

您应该使用以下方法获得想要的东西:

table1.objects.exclude(table2=some_param)

1
这仍然使您有可能不必要地从数据库中提取很多记录。
杰伊·泰勒

5
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])

1

您可以为Django查询编写自定义查找:

文档 “让我们从一个简单的自定义查询,我们将编写一个自定义查找NE其工作相对精确Author.objects.filter(name__ne =‘杰克’)将转换为SQL:"author"."name" <> 'Jack'

from django.db.models import Lookup

class NotEqual(Lookup):
    lookup_name = 'ne'

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return '%s <> %s' % (lhs, rhs), params

-16
[o1 for o1 in table1.objects.all() if o1.id not in [o2.id for o2 in table2.objects.filter(id=some_parm)]]

或更好

not_in_ids = [obj.id for obj in table2.objects.filter(id=some_parm)]
selected_objects = [obj for obj in table1.objects.iterator() if obj.id not in not_in_ids]

12
遍历表中的每一行。gg
Rebs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.