You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF APIView自定义分页如何处理EmptyPage异常返回合法响应

DRF 分页 EmptyPage 异常处理方案

PageNumberPagination 触发EmptyPage报错的原因是:用户传入的页码值大于分页总页数时,底层Django分页器找不到对应页数据直接抛出异常,没有做兜底处理。以下两种方案都可以解决问题,优先选第一种,侵入性最低。


方案1:重写自定义分页类逻辑(推荐)

直接修改你现有CustomPagination类的paginate_queryset方法,在分页逻辑里直接捕获异常做兜底,不需要修改任何视图、Mixin代码,所有用这个分页类的接口自动生效。

from rest_framework import pagination
from django.core.paginator import EmptyPage, PageNotAnInteger


class CustomPagination(pagination.PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    max_page_size = 10
    page_query_param = 'p'

    def paginate_queryset(self, queryset, request, view=None):
        page_num = request.query_params.get(self.page_query_param, 1)
        page_size = self.get_page_size(request)
        paginator = self.django_paginator_class(queryset, page_size)
        total_pages = paginator.num_pages

        try:
            self.page = paginator.page(page_num)
        except PageNotAnInteger:
            # 传入的页码不是整数时,默认返回第一页
            self.page = paginator.page(1)
        except EmptyPage:
            # 页码超出范围时的兜底逻辑,二选一即可
            # 选项1:自动返回最后一页的有效数据
            self.page = paginator.page(total_pages)
            # 选项2:返回空结果集,和正常分页结构保持一致
            # self.page = paginator.page(1)
            # self.page.object_list = self.page.object_list.none()

        self.request = request
        if paginator.num_pages > 1 and self.template is not None:
            self.display_page_controls = True
        return list(self.page)

改完之后,不管请求传p=999这种超出范围的页码,还是传非数字的页码值,都不会抛出500错误,返回的响应结构和正常分页完全一致,前端不需要额外适配异常格式。


方案2:全局异常统一拦截

如果项目里有多个分页类,不想逐个修改,可以通过DRF全局异常处理器统一捕获分页相关异常,所有接口自动生效。

  1. 先写自定义异常处理函数:
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.core.paginator import EmptyPage, PageNotAnInteger


def global_exception_handler(exc, context):
    # 先走DRF默认的异常处理逻辑
    resp = exception_handler(exc, context)

    # 单独处理分页类异常
    if isinstance(exc, (EmptyPage, PageNotAnInteger)):
        # 响应内容、状态码可以根据前后端约定调整
        return Response(
            {
                "count": 0,
                "next": None,
                "previous": None,
                "results": [],
                "msg": "请求页码无效"
            },
            status=status.HTTP_200_OK
        )
    return resp
  1. 在项目settings.py的DRF配置里注册这个异常处理器:
REST_FRAMEWORK = {
    # 你原有的其他DRF配置...
    'EXCEPTION_HANDLER': '你的项目代码目录路径.global_exception_handler',
}

补充说明

你现有的PaginationHandlerMixin和视图类代码不需要做任何修改,上面两种方案都可以直接兼容。如果只有单个接口需要特殊处理页码异常,也可以直接在视图的get方法里用try/except包裹paginate_queryset调用做单独处理,不过这种方式会产生重复代码,不推荐大规模使用。

内容的提问来源于stack exchange,提问作者Hossein Gholami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:09:17