问题
前端列表在第3页进行搜索的时候,当搜索的结果数据小于20个的时候,drf的view_set的list接口会报NotFound: Invalid page。
想要的效果是在第N页搜索的时候,若数据足够,则停留在第N页,不足则停留在最后一页。
上代码
视图为
class HistoryViewSet(ReModelViewSet):
queryset = History.objects.all()
serializer_class = HistorySerializer
filter_class = HistoryFilter
http_method_names = ['get']
作用查询历史日志列表
api接口信息为:
Request URL: http://127.0.0.1:8000/history/?name=&eta_gte=&eta_lte=&page=1&page_size=10&state=
Request Method: GET
api返回值
{
"message": "success",
"code": "OK",
"data": {
"count": 22,
"info": [
{
"id": 21,
"process_id": 3,
"name": "aaaaaaa",
"state": "error",
"eta": "2020-10-21 14:54:30",
"create_time": "2020-10-22 06:00:04",
"start_time": "2020-10-21 14:53:58"
},
{
"id": 22,
"process_id": 4,
"name": "vv",
"state": "success",
"eta": "2020-10-21 14:59:42",
"create_time": "2020-10-22 06:00:04",
"start_time": "2020-10-21 14:59:43"
}
]
},
"result": true
}
刨析问题
接口请求过来的时候会执行到
rest_framework.mixins.ListModelMixin#list这个函数,
执行到断点位置就报错了。
进入paginate_queryset查看
跳入这里
rest_framework.generics.GenericAPIView#paginate_queryset
再进一步查看rest_framework.pagination.PageNumberPagination#paginate_queryset
执行到这个断点位置发生了问题。
通过查看代码可以发现解决page_number的值问题就OK了。
解决方法
重写list
def my_rep_list(obj, request, *args, **kwargs):
queryset = obj.filter_queryset(obj.get_queryset())
total = len(queryset)
page_size = int(request.query_params['page_size'])
if total == 0:
request.query_params['page'] = 1
else:
if int(request.query_params['page']) * (page_size - 1) >= total:
request.query_params['page'] = int(math.ceil(float(total) / page_size))
page = obj.paginate_queryset(queryset)
if page is not None:
serializer = obj.get_serializer(page, many=True)
return obj.get_paginated_response(serializer.data)
class HistoryViewSet(ReModelViewSet):
queryset = History.objects.all()
serializer_class = HistorySerializer
filter_class = HistoryFilter
http_method_names = ['get']
def list(self, request, *args, **kwargs):
return my_rep_list(self, request, *args, **kwargs)