der 入门-精通 09days

发布时间 2023-12-28 15:13:42作者: 拆尼斯、帕丁顿

排序

排序快速使用(GenericAPIView)

1.只有查询所有需要排序

2. 如何使用

1 必须是继承 GenericAPIView 及其子类
    2 在类中配置类属性
        filter_backends = [OrderingFilter]
    3 类中写属性
        ordering_fields = ['price','id']  # 必须表的字段
        
    4 以后再前端,就可以访问
        http://127.0.0.1:8000/api/v1/books/?ordering=price 按price升序排
        http://127.0.0.1:8000/api/v1/books/?ordering=-price 按price降序排
        http://127.0.0.1:8000/api/v1/books/?ordering=-price,id

继承APIview写排序

如果继承APIView,过滤规则自己写
from rest_framework.views import APIView
from rest_framework.response import Response


class BookView(ViewSetMixin, APIView):
    def list(self, request):
        # 从地址栏中取出用户过滤条件
        query_params = request.query_params  # {ordering:price}
        # 支持多个条件排序  ordering=-price,id
        if ',' in query_params.get('ordering'):
            query = query_params.get('ordering').split(',')
        obj_list = Book.objects.all().order_by(*query)
        ser = BookSerializer(instance=obj_list, many=True)

        return Response(ser.data)

过滤

使用drf内置过滤类

restful规范中有一条是请求地址中带过滤条件,查询所有数据,只查询出我们想要的

 

如何使用?

1 必须是继承 GenericAPIView 及其子类
    2 在类中配置类属性
    	filter_backends = []
    3 类中写属性
    	ordering_fields = ['price','id']  # 必须表的字段
        
    4 以后再前端,就可以访问
    	http://127.0.0.1:8000/api/v1/books/?ordering=price 按price升序排
    	http://127.0.0.1:8000/api/v1/books/?ordering=-price 按price降序排
    	http://127.0.0.1:8000/api/v1/books/?ordering=-price,id

使用djagno-filter过滤

1  下载  pip3 install django-filter
2  导入  from django_filters.rest_framework import                 
                                                   DjangoFilterBackend
3 使用
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name', 'price']
    # 支持
    # http://127.0.0.1:8000/api/v1/books/?name='西游记'&price=11 #查询书名为西游记并且价格为11 的图书
    # 如何执行或条件,模糊匹配 :可以自己扩写--》                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

自定制过滤类

 

1 写个类,继承BaseFilterBackend   重写   filter_queryset,在内部完成过滤
from rest_framework.filters import BaseFilterBackend
class CommonFilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # queryset 之前所有的数据 Book.objects.all()
        # request 当次请求request
        if request.query_params.get('name'):
            queryset = queryset.filter(name__contains=request.query_params.get('name'))
        if request.query_params.get('price'):
            queryset = queryset.filter(price=request.query_params.get('price'))
        if request.query_params.get('price__gt'):
            queryset = queryset.filter(price__gt=request.query_params.get('price__gt'))
        return queryset
# 2 使用
from .filters import CommonFilter
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [CommonFilter]

继承APIView实现过滤(逻辑跟自定义完全一致)

分页

查询所有接口,分页

# 使用--》drf内置了--》三种分页方式
    - 1 写个类,继承 三个类之一  :
        PageNumberPagination, LimitOffsetPagination, CursorPagination
    -2 重写类属性
        PageNumberPagination
            page_size = 2  # 每页大小,一页显示多少条
            page_query_param = 'page'  # 分页查询条件   ?page=1     ?page =2
            page_size_query_param = 'size'  # 每页最多显示多少条的查询条
            max_page_size = 5  # 每页最多显示多少条
        LimitOffsetPagination
            default_limit = 2  # 每页显示条数
            limit_query_param = 'limit'  # 每页显示条数 的查询条数  ?limit=100  每页显示100条,如果不传,显示2条
            offset_query_param = 'offset'  # 偏移量 从第6条开始,拿30条 offset=6&limit=30
            max_limit = 5  # limit可以写很大,但是最多显示5条

        CursorPagination
            cursor_query_param = 'cursor'  # 按游标查询的查询条件 ,value值,前端是不知道的,只能通过后台返回
            page_size = 2  # 每页显示多少条
            ordering = 'id'  # 排序规则,必须是表中字段
    - 3 在继承自 GenericAPIView 及其 子类
    - 4 在视图类配置分页类即可
        # 基本分页:http://127.0.0.1:8000/api/v1/books/?page=1&size=3000
        # pagination_class = CommonPageNumberPagination  # 不要放在列表中,分页方式只能选一种

        #偏移分页 http://127.0.0.1:8000/api/v1/books/?limit=4&offset=2 从第2条开始,拿4条
        # pagination_class = CommonLimitOffsetPagination

        # 游标分页--->不能再跟排序连用了--》用的不多,app会用
        # 只能选择上一页和下一页,不能跳到某一页,但是速度快,针对于特别大数据量分页,有优势
        pagination_class = CommonCursorPagination

异常处理

# 1 读APIView源码时,即是三大认证和视图类的方法中出现了异常,都会被try捕获,做全局异常处理

# 2 捕获到,统一处理,处理成固定格式---》给前端是统一的
    {code:100,msg:成功,result:[{},{}]}
    
# 3 无论是否出异常,给前端格式都是统一的
    {code:100,msg:成功}

    
    
# 4 使用步骤
    - 1 新建py文件,写一个函数,在函数中处理异常
     from rest_framework.views import exception_handler
    from rest_framework.response import Respons
    def common_exception_handler(exc, context):
        # drf的异常,处理了
        res = exception_handler(exc, context)
        if res:  # 有值说明是drf的异常,
            # data = {'detail': exc.detail}
            # return Response(data)
            # {code: 100, msg: 成功}
            detail = res.data.get('detail') or "drf异常,请联系系统管理员"
            return Response({'code': 999, 'msg': detail})
        else: # 如果没值,说明是自己的异常
            return Response({'code': 888, 'msg': '系统异常,请联系系统管理员:%s'%str(exc)})
    - 2  把函数配置在配置文件中
        REST_FRAMEWORK = {
            'EXCEPTION_HANDLER': 'app01.exceptions.common_exception_handler',
        }
    - 3 只要三大认证或视图类的方法出了异常,就会走这个函数