Django2.2升级到3.2出现QuerySet无_deferred_filter属性报错如何解决?
报错原因
该报错是Django 2.2升级到3.2版本的常见兼容性问题,核心诱因有两个:
- Django 3.2对QuerySet内部实现做了调整,新增了
_deferred_filter私有属性用于处理延迟过滤逻辑,旧版本自定义管理器的实现逻辑没有适配该改动,导致返回的QuerySet实例缺少对应属性。 - 如果你的
SOStatuses.closed_statuses()返回的是QuerySet类型而非普通列表,在3.2的子查询解析逻辑中,会触发QuerySet实例的内部属性校验,属性缺失就会抛出该异常。如果你的自定义管理器之前配置了已经被3.2废弃的use_for_related_fields = True参数,也会导致该问题。
修复方案
你可以任选以下一种方案修复:
方案1:将过滤值转为普通列表
直接把exclude条件里的SOStatuses.closed_statuses()转为列表,规避子查询解析逻辑的兼容性问题,改动最小:
class SOActiveManager(models.Manager): def get_queryset(self): return super(SOActiveManager, self).get_queryset().exclude( status__in=list(SOStatuses.closed_statuses()) )
方案2:改用自定义QuerySet实现管理器
这是Django 3.2+推荐的自定义过滤管理器实现方式,从底层规避属性缺失问题:
# 先定义自定义QuerySet class SOActiveQuerySet(models.QuerySet): def exclude_closed(self): return self.exclude(status__in=SOStatuses.closed_statuses()) class SOActiveManager(models.Manager): def get_queryset(self): return SOActiveQuerySet(self.model, using=self._db).exclude_closed() # 模型内绑定管理器的逻辑不变 class ServiceOrders(models.Model): # 其他字段定义 active = SOActiveManager()
方案3:移除废弃配置
如果你的SOActiveManager中配置了use_for_related_fields = True,直接删除该行即可,Django 3.2已经完全移除了该参数的支持,改用base_manager_name配置关联查询的管理器。
内容的提问来源于stack exchange,提问作者James Lin
相关产品推荐
相关产品推荐

