如何在Django ModelViewSet中调用super()方法实现分页功能
问题根因
- 当前代码没有调用DRF内置的分页逻辑,直接将全量过滤后的查询集序列化返回,因此不会触发分页效果
- 你没有复用
ListModelMixin的list()方法自带的分页处理流程,手动实现的序列化逻辑跳过了分页步骤
实现方案
首先确认你已经配置了DRF分页规则,支持全局配置或者视图单独配置:
分页配置示例
全局配置(写在项目settings.py中):
REST_FRAMEWORK = { # 指定默认分页类 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 配置默认每页条数 'PAGE_SIZE': 10 }
如果只想给当前视图单独配置分页,直接在视图类中指定即可:
class RecentlyViewedVideosViewSet(ResponseViewMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): queryset = RecentlyViewedVideos.objects.all() serializer_class = RecentlyViewedVideosSerializer # 单独指定当前视图的分页类,全局已配可以省略 pagination_class = rest_framework.pagination.PageNumberPagination
代码修改(两种实现方式)
方式1:手动调用分页逻辑(适合需要高度自定义返回格式的场景)
直接修改你现有的list方法,加入分页处理步骤:
def list(self, request, **kwargs): # 处理过滤逻辑 if 'learner_id' in self.kwargs: learner_id = self.kwargs['learner_id'] else: learner_id = self.request.learner.id queryset = super().get_queryset().filter(learner_id=learner_id) # 调用分页器处理查询集 page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) # 数据放入details字段,可按需添加分页元信息 return self.jp_response( s_code='HTTP_200_OK', data={ "details": serializer.data, "total": self.paginator.page.paginator.count, "current_page": self.paginator.page.number, "total_pages": self.paginator.page.paginator.num_pages } ) # 无分页配置时返回全量数据 serializer = self.get_serializer(queryset, many=True) return self.jp_response( s_code='HTTP_200_OK', data={"details": serializer.data} )
方式2:复用super().list()逻辑(代码更简洁,符合DRF规范)
把过滤逻辑抽离到get_queryset方法,直接复用父类的list分页流程,再调整返回格式即可:
# 重写get_queryset做过滤,后续其他接口也能复用该规则 def get_queryset(self): queryset = super().get_queryset() if 'learner_id' in self.kwargs: learner_id = self.kwargs['learner_id'] else: learner_id = self.request.learner.id return queryset.filter(learner_id=learner_id) def list(self, request, **kwargs): # 调用父类list方法获取已经分页处理后的响应 original_resp = super().list(request, **kwargs) # 调整返回格式,把业务数据放入details字段 return self.jp_response( s_code='HTTP_200_OK', data={ "details": original_resp.data.pop("results"), **original_resp.data # 透传剩余的分页元信息(总条数、下一页链接等) } )
注意事项
- 如果你用的是自定义分页类,替换上述代码中的分页类为你自己的实现即可
- 第二种方式可维护性更高,后续如果要调整过滤规则,只需要修改
get_queryset方法即可,不需要改动list逻辑
内容的提问来源于stack exchange,提问作者user15361826
相关产品推荐
相关产品推荐

