如果页码超出范围,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"
})
我目前正在尝试使用我已经使用的 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"
})