过滤、排序、异常处理

过滤

#1 安装:pip3 install django-filter
#2 注册,在app中注册
#3 全局配,或者局部配
 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
#4 视图类
class BooksView(ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BooksModelSerializer
    # 过滤
    filter_fields = ('book_name', 'publish') # 配置可以按照哪个字段来过滤,可以是多个
    
# http://127.0.0.1:8000/api/day05/book/?book_name=西游记
# http://127.0.0.1:8000/api/day05/book/?publish=1
# http://127.0.0.1:8000/api/day05/book/?book_name=西游记&publish=1

排序

from rest_framework.filters import OrderingFilter
# 排序
class BooksView2(ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BooksModelSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'price')

# urls.py
path('books2/', views.Book2View.as_view()),
    
http://127.0.0.1:8000/api/day05/book2/?ordering=-price,id   # 降序
http://127.0.0.1:8000/api/day05/book2/?ordering=price,id    # 升序

如果需要在过滤以后再次进行排序,则需要两者结合!

from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
# 排序
class BooksView2(ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BooksModelSerializer
    # 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,
    # 否则过滤功能会失效
    filter_backends = [OrderingFilter, DjangoFilterBackend]
    ordering_fields = ('id', 'price')

# urls.py
path('books2/', views.Book2View.as_view()),
    
http://127.0.0.1:8000/api/day05/book2/?ordering=-price   # 降序
http://127.0.0.1:8000/api/day05/book2/?ordering=price    # 升序

分页

  • 只有查所有才需要分页

drf内置了三种分页方式

1、PageNumberPagination

"""
PageNumberPagination
	page_size:每页展示得条数
	page_query_param:每页得前缀参数,默认是page
	page_size_query_param:可以在url中控制展示多少条数据
	max_page_size:每页最大显示条数
"""
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
    page_size = 3   # 每页条数
    # http://127.0.0.1:8000/api/books2/?aaa=1
    page_query_param = 'page'  # 指定每页得前缀参数,默认是page
    page_size_query_param = 'size'   # 每一页显示的条数
    max_page_size = 5   # 每页最大显示条数
class BookListAPIView(ListAPIView):
    queryset = models.Book.objects.all().filter(is_delete=False)
    serializer_class = ser.BookModelSerializer
    # 配置分页
    # pagination_class = PageNumberPagination  # 内置(无法修改四个属性)
    pagination_class = MyPageNumberPagination  # 自定制
    
# 继承APIView
class Mypage(PageNumberPagination):
    page_size = 2
    page_query_param = 'page'
    # 定制传参
    page_size_query_param = 'size'
    # 最大一页的数据
    max_page_size = 5
class  Pager(APIView):
    def get(self,request,*args,**kwargs):
        # 获取所有数据
        ret=models.Book.objects.all()
        # 创建分页对象
        page=Mypage()
        # 在数据库中获取分页的数据
        page_list=page.paginate_queryset(ret,request,view=self)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        # return Response(ser.data)
        # 这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数(了解即可)
        return page.get_paginated_response(ser.data)

配置文件中指定PAGE_SIZE

REST_FRAMEWORK = {
    'PAGE_SIZE': 2,
}

2、LimitOffsetPagination

"""
LimitOffsetPagination
	default_limit = 1  默认展示条数
	limit_query_param = 'limit'  url修改展示条数的前缀词
	# http://127.0.0.1:8000/api/books2/?limit=1&offset=1,此处页面展示一条数据,该数据pk为2
	offset_query_param = 'offset' 标杆位置的前缀词,标杆是几就从标杆的后一位开始展示
	max_limit = None 最大显示条数
"""
from rest_framework.pagination import LimitOffsetPagination
class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 1   # 默认展示条数
    limit_query_param = 'limit'   # url修改展示条数的前缀词
    offset_query_param = 'offset'   # 标杆位置的前缀词,标杆是几就从标杆的后一位开始展示
    max_limit = 5   # 最大显示条数
    
class BookListAPIView(ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = ser.BookModelSerializer
    # 配置分页
    pagination_class = MyLimitOffsetPagination
    
# APIView
class  Pager(APIView):
    def get(self,request,*args,**kwargs):
        # 获取所有数据
        ret=models.Book.objects.all()
        # 创建分页对象
        page=LimitOffsetPagination()
        # 在数据库中获取分页的数据
        page_list=page.paginate_queryset(ret,request,view=self)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        # return page.get_paginated_response(ser.data)
        return Response(ser.data)

3、CursorPagination

"""
CursorPagination
    cursor_query_param = 'cursor'  # 每页得前缀参数,默认是cursor
    page_size = 2   # 每页显示条数
    ordering = 'id'  # 排序字段,字段不存在则报错,默认升序,降序:-字段名
"""
from rest_framework.pagination import CursorPagination
class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 每页得前缀参数,默认是cursor
    page_size = 2   # 每页显示条数
    ordering = 'id'  # 排序字段,字段不存在则报错
class BookListAPIView(ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = ser.BookModelSerializer
    # 配置分页
    pagination_class = MyCursorPagination

# APIView
# 看源码,是通过sql查询,大于id和小于id
class  Pager(APIView):
    def get(self,request,*args,**kwargs):
        # 获取所有数据
        ret=models.Book.objects.all()
        # 创建分页对象
        page=CursorPagination()
        page.ordering='nid'
        # 在数据库中获取分页的数据
        page_list=page.paginate_queryset(ret,request,view=self)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        # 可以避免页码被猜到
        return page.get_paginated_response(ser.data)

异常处理(需要统一接口返回)

# 自定义异常方法,替换掉全局
# 写一个方法
# 自定义异常处理的方法
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
def my_exception_handler(exc, context):
    response = exception_handler(exc, context)
    # response两种情况,一种是None,drf没有处理,交给django处理,直接返回了异常页面
    # 另一种是response对象,django处理了但是不符合要求
    # 我们需要统一要求,但凡抛异常都让它以json格式返回
    print(type(exc))

    if not response:
        if isinstance(exc, ZeroDivisionError):
            return APIResponse(code=777, message='1/0错误', status=status.HTTP_400_BAD_REQUEST)
        return APIResponse(code=999, message=str(exc), status=status.HTTP_400_BAD_REQUEST)

    else:
        return APIResponse(code=888, message=response.data.get('detail'), status=status.HTTP_400_BAD_REQUEST)
    
# 全局配置setting.py
'EXCEPTION_HANDLER': 'xxx.user_auth.my_exception_handler',
    
class TestView2(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request):
        1/0
        return APIResponse(message='游客访问')

封装Response方法

from rest_framework.response import Response
from rest_framework.status import HTTP_200_OK


class APIResponse(Response):
    def __init__(self, code=100, message='成功', result=None, status=HTTP_200_OK, headers=None, **kwargs):
        back_dic = {
            'code': code,
            'message': message
        }
        back_dic.update(kwargs)
        if result:
            back_dic['result'] = result
        super().__init__(data=back_dic, status=status, headers=headers)
posted @ 2020-07-10 17:36  群青-Xi  阅读(136)  评论(0编辑  收藏  举报