升级至Django3.2后Sum聚合报CharField不支持eq查找,调整后聚合结果为None
问题核心诱因
触发Unsupported lookup 'eq'的原因
- Django 内置的精确匹配查询lookup为
exact(字段查询不写后缀时默认启用),从未注册名为eq的内置查询转换规则。 - Django 1.11版本对查询解析的容错逻辑宽松,遇到未定义的lookup后缀时会静默忽略,自动将
Type__eq=xxx等价为Type=xxx执行,因此老代码可正常运行。 - 从Django 2.0开始逐步收紧查询解析的校验规则,3.2版本会对所有链式lookup做严格的存在性校验,遇到未注册的lookup名称就会直接抛出
FieldError。
去掉__eq后聚合结果全为None的原因
- 从模型定义可知,
schedule.Type字段的choices配置为[(tag.name, tag.value) for tag in scheduleChoice],数据库中实际存储的是枚举成员的name属性值,也就是"G"、"D"这类短字符串。 - 代码中直接将
scheduleChoice.G、scheduleChoice.D这类Enum成员对象传入查询条件,而非其对应的数据库存储值。Enum成员是独立的Python对象,无法和数据库内的字符串值完成匹配,导致过滤条件命中0条记录。 Sum聚合函数对空数据集的计算返回值就是None,因此所有聚合结果都会显示为None。
修复方案
- 移除无效的
__eqlookup后缀,使用Django标准的精确匹配语法构造查询。 - 传入查询参数时,取枚举成员对应的数据库存储值,不要直接传Enum对象。
- 同步修正模型字段的默认值配置,避免后续写入新记录时出现值类型不匹配的问题。
修正后的代码示例:
# 修正后的聚合过滤器 typefilter = Sum( 'Minutes', filter=( Q(Type=scheduleChoice.G.name) | Q(Type=scheduleChoice.D.name) ) ) # 修正后的模型Type字段定义 Type = models.CharField( max_length=2, choices=[(tag.name, tag.value) for tag in scheduleChoice], default=scheduleChoice.G.name, )
补充说明:Django 3.0+原生支持
models.TextChoices枚举类型,可替代手动编写的Enum类与choices列表,减少这类值不匹配的问题。
内容的提问来源于stack exchange,提问作者janekpel
相关产品推荐
相关产品推荐

