如果页码超出范围,Django PageNumberPagination 自定义错误

Django PageNumberPagination customize error if page number out of range

我目前正在尝试使用我已经使用的 django-rest-framework 创建一个 API return 对象列表,其中包含从 url 参数输入的页面和每页限制在我的 api 视图中使用自定义分页

完成
class PropertyListPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'

    def get_paginated_response(self, data):
        return Response({
            'code': 200,
            'data': data
        })

@api_view(['GET'])
def property_list(request):
    if request.method == 'GET':
        paginator = PropertyListPagination()
        queryset = Property.objects.all()
        context = paginator.paginate_queryset(queryset, request)
        serializer = PropertySerializer(context, many=True)
        return paginator.get_paginated_response(serializer.data)

当前如果页面超出范围(例如,如果我只有 2 个对象并且我将 url 设置为 page=3 和 page_size=1 那么它应该超出范围total objects) 然后在响应中它将 return 一个 404 状态并且在正文中:

{
    "detail": "Invalid page."
}

有没有办法将其自定义为 return 400 状态和以下 json 正文?

{
    "code": 400,
    "error": "Page out of range"
}

谢谢

你可以通过覆盖NotFound class然后paginate_queryset方法来实现它,

from rest_framework.exceptions import NotFound  
from rest_framework.exceptions import APIException

class NotFound(APIException):
    status_code = status.HTTP_400_BAD_REQUEST
    default_detail = ('bad_request.')
    default_code = 'bad_request'

class PropertyListPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'

    def paginate_queryset(self, queryset, request, view=None):
        """
        Paginate a queryset if required, either returning a
        page object, or `None` if pagination is not configured for this view.
        """
        page_size = self.get_page_size(request)
        if not page_size:
            return None

        paginator = self.django_paginator_class(queryset, page_size)
        page_number = request.query_params.get(self.page_query_param, 1)
        if page_number in self.last_page_strings:
            page_number = paginator.num_pages

        try:
            self.page = paginator.page(page_number)
        except Exception as exc:
            # Here it is
            msg = {
                "code": 400 # you can remove this line as now the status code will be 400 by default as we have override it in `NotFound` class(see above)
                "error": "Page out of range"
            }
            raise NotFound(msg)

        if paginator.num_pages > 1 and self.template is not None:
            # The browsable API should display pagination controls.
            self.display_page_controls = True

        self.request = request
        return list(self.page)

你可以简单的,将分页代码包裹在try-except中,这只是我找到的一个临时解决方案。

预计将执行块而不是{"detail": "Invalid page."} message

try :
    context = paginator.paginate_queryset(filteredData, request)
    serializer = AuthUserSerializer(context,many=True)
    return Response(serializer.data)
except:
    # return here any message you want
    return Response({
        "code": 400,
        "error": "Page out of range"
    })