DRF过滤、排序、异常处理、自定义Response、分页
目录
过滤
# pip安装
# settings.py注册
# 全局配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.backends.DjangoFilterBackend'],
}
class NewNewBooksView(ListAPIView):
filter_fields = ('name',)
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
re_path('books/v5/', views.NewNewNewBooksView.as_view()),
# 在路由配置中无需正则分组即可从类似http://127.0.0.1:8000/books/v5/?name=《456》的URL中提取过滤条件
注意:继承APIView或者View的视图类是不受过滤影响的,继承了GenericAPIView类或者其子类的视图类才受过滤影响
局部过滤
# 一般情况下都是局部过滤,直接在视图类中配置即可
class NewNewNewBooksView(ListAPIView, CreateAPIView):
authentication_classes = []
throttle_classes = []
filter_backends = [DjangoFilterBackend] # 配置过滤类
filter_fields = ('name',) # 配置过滤字段
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
排序
# 全局使用
class NewNewNewBooksView(ListAPIView, CreateAPIView):
authentication_classes = []
throttle_classes = []
filter_backends = [DjangoFilterBackend,OrderingFilter]
filter_fields = ('id','price')
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
http://127.0.0.1:8000/books/v5/?ordering=-id
http://127.0.0.1:8000/books/v5/?ordering=price
异常处理
def app01_exception_handler(exc, context):
response = exception_handler(exc, context)
if not response:
return Response(data={'status': 1, 'msg': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(data={'status': 2, 'msg': response.data.get('detail')}, status=status.HTTP_400_BAD_REQUEST)
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.views.app01_exception_handler',
}
封装Response对象
class APIResponse(Response):
def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None,**kwargs):
dict = {'code': code, 'msg': msg}
if data:
dict = {'code': code, 'msg': msg, 'data': data}
dict.update(kwargs)
super().__init__(data=dict, status=None,headers=None,
exception=False, content_type=None)
book_ser = BookModelSerializer(instance=book,data=request.data,partial=True) # 部分修改
分页
三种分页方式
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
PageNumberPagination
from rest_framework.pagination import PageNumberPagination,
class BookView(ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = PageNumberPagination
REST_FRAMEWORK = {
'PAGE_SIZE': 2,
}
# page_size 即'PAGE_SIZE'
# page_query_param 即URL中的页码key
# page_size_query_param 指定为'size'即可在URL中传入size参数控制索取条数
# max_page_size 硬性规定每页最大条数
# 可以通过如下继承改变参数值
LimitOffsetPagination
from rest_framework.pagination import LimitOffsetPagination
class MYLimitOffsetPagination(LimitOffsetPagination):
default_limit = settings.REST_FRAMEWORK['PAGE_SIZE'] # 每页数据条数
limit_query_param = 'limit' # 指定每页条数的key
offset_query_param = 'offset' # 相对起始位置偏移量,offset=2则从第三条开始取
max_limit = None # 每页最大条数
class BookView(ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = MYLimitOffsetPagination
CursorPagination
from rest_framework.pagination import CursorPagination
class MYLimitOffsetPagination(CursorPagination):
cursor_query_param = 'cursor' # 过滤key
page_size = 3 # 每页条数
ordering = '-id' # 排序字段
class BookView(ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = MYLimitOffsetPagination
# 只有向前向后两个按钮,无法跳跃到某一页或者某一条数据,但是相比上面两种效率更高
使用APIView创建视图类时分页
class BooksAPIView(APIView):
def get(self, request, *args, **kwargs):
book_list = models.Book.objects.filter(is_delete=False)
page_cursor = PageNumberPagination()
book_list = page_cursor.paginate_queryset(book_list,request,view=self)
book_list_ser = BookModelSerializer(book_list, many=True)
return Response(data=book_list_ser.data)