Django REST Framework过滤查询集时仅单次访问数据库的方法
解决Django REST Framework中查询集N+1查询问题
问题根源
你碰到的N次SELECT冗余查询,核心原因不是返回查询集本身,而是序列化器中包含了未预取的关联模型字段。Django查询集是惰性求值的,返回Model.objects.filter(...)本身不会触发数据库查询,但当DRF序列化每条数据时,若访问了未预取的关联对象,就会为每条数据单独发起一次SELECT请求,形成N+1查询。而你尝试的list()只是提前加载主表数据到内存,既解决不了关联字段的N+1问题,还会额外增加内存开销导致响应变慢。
解决方案
直接在查询集里用Django提供的预取方法,一次性把关联数据拉取回来,避免多次查询:
- 针对外键/一对一关联:使用
select_related
如果你的Model包含外键或一对一类型的关联字段(比如author),修改get_queryset方法:
class ModelViewset(ListModelMixin, viewsets.GenericViewSet): def get_queryset(self): # 替换为你的关联字段名 return Model.objects.filter(category=value).select_related('author')
- 针对多对多/反向外键关联:使用
prefetch_related
如果是多对多字段(比如tags)或反向外键关联,用这个方法:
class ModelViewset(ListModelMixin, viewsets.GenericViewSet): def get_queryset(self): # 替换为你的关联字段名 return Model.objects.filter(category=value).prefetch_related('tags')
- 精简序列化器字段
如果序列化器中有些关联字段不是接口必需的,直接移除这些字段,从根源上避免不必要的关联查询。
补充说明
select_related是通过SQL的JOIN语句一次性拉取关联数据,适合一对一/外键这类单条关联的场景。prefetch_related是先拉取主表数据,再批量拉取关联表数据,适合多对多、反向外键这类多条关联的场景。
内容的提问来源于stack exchange,提问作者Pradeep
相关产品推荐
相关产品推荐

