You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django3.0空列表__in取反的When生成错误SQL报ProgrammingError

问题根因

这是Django 3.0及更早版本的ORM优化缺陷:当ORM处理__in=[]条件时,会默认将正向Q查询优化为永假表达式,但对应取反Q对象的优化逻辑存在缺失,没有把~Q(__in=[])正确转换为永真表达式,反而直接清空了条件内容,最终生成CASE WHEN THEN的非法SQL语法,触发django.db.utils.ProgrammingError报错。

两个对照示例不会触发问题的原因:

  • 正向Q(__in=[])的优化逻辑完整,ORM会直接判定该条件永假,Case语句直接走默认值,因此生成的SQL逻辑正常
  • __in参数非空时不会触发空列表的特殊优化逻辑,取反操作可以正常生成SQL条件

Django 3.2及以上版本已经修复了该缺陷,后续升级版本后可以直接使用原有写法。

不升级Django的解决方案

最稳妥的方案是提前对__in的查询参数做判空处理,动态构造When条件,绕过ORM的优化bug:

# 这里的unit_list是你要传入__in查询的参数
unit_list = []

# 空列表时提前处理条件:~Q(field__in=[]) 等价于永真条件
if not unit_list:
    when_condition = When(True, then=Value(False))
else:
    when_condition = When(~Q(case__assigned_unit__in=unit_list), then=Value(False))

# 执行查询
Activity.objects.all().annotate(
    employee_authorized=Case(
        when_condition,
        default=Value(True),
        output_field=BooleanField(),
    )
)

如果不想做分支判断,也可以直接将空列表场景下的取反条件替换为通用永真表达式,比如Q(pk__isnull=False),也可以达到同样的效果,避免触发bug。

内容的提问来源于stack exchange,提问作者Rik Schoonbeek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 20:24:01