"Q" 与“__in”不一致的 Django ORM 查询结果

Inconsistent Django ORM Query Results With "Q" vs "__in"

我正在尝试查找我的一个模型的所有实例,这些实例的属性设置为 None 或空字符串。我想我遗漏了一些关于 ORM 的 __in 查询。

TextBlock.objects.filter(content='').count()
>185
TextBlock.objects.filter(content=None).count()
>235
TextBlock.objects.filter(content__in=['', None]).count()
>185
TextBlock.objects.filter(Q(content='')|Q(content=None)).count()
>420
TextBlock.objects.filter(content__in=[None, '']).count()
>185

当我使用 IntegerFIeld 而不是使用 None 或空字符串时,我得到:

TextBlock.objects.filter(order=1).count()
> 575046
TextBlock.objects.filter(order=2).count()
> 11946
TextBlock.objects.filter(order__in=[1,2]).count()
> 586992 

这是我所期望的。我期望 TextBlock.objects.filter(content__in=['', None]).count() 到 return 420 个结果是错误的吗?如果是,为什么?

Q 查询执行了我想要的操作,所以我最终会使用它,但我仍然很好奇为什么第三个查询没有执行我想要的操作。

谢谢!

编辑:不确定是否有所不同,但内容字段是 models.TextField 并且订单字段是 models.IntegerField

为了检查内容是否 None,您不应该使用比较。 你必须在 ORM 中使用 content__isnull (您可以像现在一样将查询与 Q 对象结合起来)

您使用 isnull 字段查找检查 None 值:

TextBlock.objects.filter(Q(content='')|Q(content__isnull=True)).count()

注意NULL == NULL在SQL中实际上是假的,你需要使用IS NULL来检查一个值是否为空。 Django 足够聪明,可以将 Q(content=None) 转换为 IS NULL 语句,这就是为什么 TextBlock.objects.filter(Q(content='')|Q(content=None)).count() returns 是您期望的结果。

IN 语句只能将值与其元素进行比较,不能进行 IS NULL 检查。要检查空值,您需要显式添加 content=None 或等效的 content__isnull=True.

对于不包含 NULL 的任何值列表,使用 __in 的查询应该按预期工作。