DRF全局分页需在settings.py配置DEFAULT_PAGINATION_CLASS和PAGE_SIZE,仅对GenericAPIView及子类(如ModelViewSet、ListAPIView)生效;纯APIView或函数视图不支持,且PAGE_SIZE为None会返回全部数据而非不限制。

DRF全局分页怎么配PageNumberPagination
直接在settings.py里配DEFAULT_PAGINATION_CLASS和PAGE_SIZE就能生效,不用每个视图都写pagination_class。
但要注意:只有继承GenericAPIView或使用ModelViewSet等 DRF 提供的视图类时才自动触发;纯APIView或函数视图不会走这个逻辑。
-
REST_FRAMEWORK配置必须放在settings.py顶层,不是drf子模块下 -
PAGE_SIZE设为None会禁用分页,不是“不限制”——它会让分页器直接返回全部数据,可能撑爆内存 - 如果项目里混用了
LimitOffsetPagination或自定义分页器,得确认没被其他地方覆盖掉全局设置
PageNumberPagination的page_size_query_param怎么开
默认只认page和page_size固定参数,但用户常想用?size=20&num=2这类更灵活的写法。
需要自己继承并改写,不能靠配置项开关:
class CustomPageNumberPagination(PageNumberPagination):
page_size_query_param = 'size'
page_query_param = 'num'
- 重命名
page_query_param后,?page=2就失效了,只认?num=2 -
page_size_query_param设为空字符串('')会导致 500 错误,必须是合法字段名 - 前端传非数字值(如
?size=abc)会返回400 Bad Request,错误信息里带"page_size" must be a number
为什么PageNumberPagination在ListAPIView里不生效
最常见原因是视图类没正确继承,或者手动写了get_queryset()但忘了调用super()导致分页器拿不到原始QuerySet。
- 检查是否用了
APIView而不是GenericAPIView——前者压根不集成分页逻辑 - 如果重写了
list()方法,但没调用self.paginate_queryset()和self.get_paginated_response(),分页就等于没开 -
queryset属性是None或没定义,也会让paginate_queryset返回空列表,看起来像“没数据”
性能坑:大表+高页码时PageNumberPagination变慢
PageNumberPagination底层用OFFSET实现,?page=10000&page_size=20会跳过 199980 条记录,MySQL/PostgreSQL 都扛不住。
- 超过 1000 页建议切到
CursorPagination,它基于游标+排序字段,不依赖偏移量 - 加数据库索引时,必须包含
ordering字段(比如created_at),否则游标分页也慢 -
PageNumberPagination的max_page_size只是限制参数上限,拦不住用户传?page=999999——得配合业务校验或中间件拦截
分页不是配完就完事,关键看数据量、访问模式和索引是否跟得上。尤其当count()变成慢查询时,连总页数都算不出来,这时候PageNumberPagination就该换掉了。










