DRF - 分页器、异常处理、封装Response
分页器
一:分页器简介
DRF内置了3种分页器
分页器 | 中文 | 介绍 |
---|---|---|
PageNumberPagination | 普通分页 | 非常常用,拥有上一页下一页,同时也可以做诸如1,2,3,4这样的跳转页数 |
LimitOffsetPagination | 偏移分页 | 相对使用较少,有一个基准点,可以根据这个基准点进行左偏移和右偏移 |
CursorPagination | 游标分页 | 效率最高,速度最快,只有上一页和下一页,不可以做页数的跳转 |
APIView
:分页需要自己写GenericAPIView+ListModelMixin
:直接用
二:PageNumberPagination
- 普通分页
参数设置
参数 | 释义 |
---|---|
page_size = 3 | 每页显示的条数 |
page_query_param = 'page' | 查询的时候指定跳转到第几页 |
page_size_query_param = 'size' | 查询的时候指定每页显示的条数 |
max_page_size = 5 | 每页最大显示条数(相当于手动限制) |
使用方式
- 定义1个类,继承
PageNumberPagination
- 重写上面的4个属性
- 在继承
GenericAPIView+ListModelMixin
的视图类中配置
pagination_class = MyPage
实例
class MyPageNumberPagination(PageNumberPagination):
page_size = 3 # 每页条数
page_query_param = 'page' # 第几页
page_size_query_param = 'size' # 取几条
max_page_size = 5 # 每页最多几条
from rest_framework.pagination import PageNumberPagination
from rest_framework.generics import ListAPIView
from frequence.serializer import BookSerializer
from frequence.models import Book
class MyPageNumberPagination(PageNumberPagination):
page_size = 3 # 每页条数
page_query_param = 'page' # 第几页
page_size_query_param = 'size' # 取几条
max_page_size = 5 # 每页最多几条
class BookView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = MyPageNumberPagination
三:LimitOffsetPagination
- 偏移分页
参数
参数 | 释义 |
---|---|
default_limit = 3 | 每页默认显示条数 |
limit_query_param = 'limit' | 查询时,指定显示几条 |
offset_query_param = 'offset' | (标杆)查询时,指定的起始位置是哪里 |
max_limit = 5 | 查询时,最多返回几条 |
例
limit=2&offset=5
:从位置5开始,往后取2条(取出6、7)limit=1&offset=3
:从位置3开始,往后取1条(取出4)
实例
class MyLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3 # 每页条数
limit_query_param = 'limit' # 往后拿几条
offset_query_param = 'offset' # 标杆
max_limit = 5 # 每页最大几条
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.generics import ListAPIView
from frequence.serializer import BookSerializer
from frequence.models import Book
class MyLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3 # 每页条数
limit_query_param = 'limit' # 往后拿几条
offset_query_param = 'offset' # 标杆
max_limit = 5 # 每页最大几条
class BookView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = MyLimitOffsetPagination
四:CursorPagination
- 游标分页
参数
参数 | 释义 |
---|---|
page_size = 2 | 每页显示的条数 |
ordering = 'pk' | 排序字段(必填) |
cursor_query_param = 'cursor' | 每一页查询的key |
page_size_query_param = 'size' | 查询时,每一页显示几条 |
max_page_size | 查询时,最多返回几条 |
实例
class MyCursorPagination(CursorPagination):
cursor_query_param = 'cursor' # 每一页查询的key
page_size = 2 # 每页显示的条数
ordering = 'pk' # 排序字段
from rest_framework.pagination import CursorPaginationfrom rest_framework.generics import ListAPIView
from frequence.serializer import BookSerializer
from frequence.models import Book
class MyCursorPagination(CursorPagination):
cursor_query_param = 'cursor' # 每一页查询的key
page_size = 2 # 每页显示的条数
ordering = 'pk' # 排序字段
class BookView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = MyCursorPagination
五:继承APIView - 最原始分页的使用
实例
class BookAPIView(APIView):
def get(self, request):
book_list = Book.objects.all().order_by('id')
# 只需更换不同的分页类即可
page = MyPageNumberPagination
# page = MyLimitOffsetPagination
# page = MyCursorPagination
res = page.paginate_queryset(book_list, request, self)
ser = BookSerializer(res, many=True)
return page.get_paginated_response(ser.data)
异常处理
一:异常
DRF一般用于前后端分离的项目
但是,一旦出现了异常,页面就会变成这个样纸
在Postman
中就会变成这个样子
但是,我们想得到的并不是这样的页面,而是错误的数据,类似于
{
“status”: "404 Not Found",
"msg": "Your Client Has Error"
}
二:自定义全局异常
代码
定义一个utils.py
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
def capture_exception(exc, context):
response = exception_handler(exc, context)
if response is None:
response = Response({'code': 666, 'detail': '发生了未知错误'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return response
在settings.py
中配置
REST_FRAMEWORK = {
'EXCEPTION_HANDLER':'frequence.utils.capture_exception'
}
手动测试异常
views.py
class Mine(object): # 手动定义1个类,无意义
pass
class BookView(ListAPIView):
queryset = Book.objects.all()
serializer_class = Mine # 引用无意义的类,肯定会抛出异常
pagination_class = MyCursorPagination
封装Response
创建
创建1个utils.py
class APIResponse(Response):
def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
dic = {'code': code, 'msg': msg}
if data:
dic['data'] = data
dic.update(kwargs) # 这里使用update
super().__init__(data=dic, status=status,
template_name=None, headers=headers,
exception=False, content_type=content_type)
使用
在视图函数中
return APIResponse(code=100,msg='查询成功',data=ser.data,count=200,next='http://wwwa.asdfas')