Django 在查询中/未在查询中

我正在尝试弄清楚如何用 django 写一个“ not in”样式的查询。 例如,我考虑的查询结构如下所示。

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

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

86389 次浏览
[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]

这些模型:

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)
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])
table1.objects.exclude(id__in=
table2.objects.filter(your_condition).values_list('id', flat=True))

排除函数的工作方式与请求的 Not运算符类似。属性 flat = True告诉 table2查询将 value_list作为一个级别列表返回。因此... 最后,您将从 table2获得一个 IDs列表,您将使用该列表在 table1中定义条件,这将被排除函数拒绝。

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

来自 documentation: ”让我们从一个简单的自定义查找开始。我们将编写一个与 一模一样相反的自定义查找 Author.objects.filter(name__ne='Jack')将转换为 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

接受的答案是可以的,但是我将提供一种更加可操作的新方法。

from django.db.models import Q


query = Q(id__in=table2.objects.filter(your_condition).values_list('id'))
table1.objects.filter(~query)

如果使用主键,则不需要调用 value _ list ()。

Q ()对象上的“ ~”类似于“ not”操作符。

我想这种方法使代码更加可重用,并且允许您仅仅通过将 Q ()对象存储在 vars 上就可以完成“任何”类型的动态工作。