• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    DRF过滤排序分页异常处理的过程记录

    一、过滤

    对于列表数据要通过字段来进行过滤,就需要添加 django-filter 模块

    使用方法:

    # 1、注册,在app中注册 settings.py
    INSTALLED_APPS = [
        'django_filters',
    ]
    
    # 2、settings.py 配置
    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': (
            'django_filters.rest_framework.DjangoFilterBackend',
        )
    }
    
    # 3、在视图中添加filter_fields属性,指定过滤的字段
    class BooksView(ModelViewSet):
        queryset = Books.objects.all()
        serializer_class = BooksSerializer
    
        filter_fields = ('title',) # 配置可以按照哪个字段来过滤
        
    # http://127.0.0.1:8000/books/?title=红楼梦
    
    

    二、排序

    排序可以使用 Rest Framework 提供的 OrderingFilter 来快速指明数据按指定字段进行排序

    使用方法:

    # 1、首先视图中设置filter_backends=[OrderingFilter]
    # 2、然后再视图中添加 ordering_fields 属性,指定排序字段
    
    from rest_framework.filters import OrderingFilter
    class BooksView(ModelViewSet):
        queryset = Books.objects.all()
        serializer_class = BooksSerializer
    
        filter_backends = [OrderingFilter] # 第一步
        ordering_fields = ['price','id'] # 第二步
        
    # http://127.0.0.1:8000/books/?ordering=id 通过ordering查看有无指明排序的字段,并通过字段来排序
    # -id 表示针对id字段进行倒序排序
    # id  表示针对id字段进行升序排序
    
    

    三、分页

    首先 Rest Framework 提供了三种分页方式,并且

    使用方式一:可以直接继承使用,但是配置参数需要在settings.py里面配置

    使用方式二:通过子类继承父类分页器使用,直接在子类中修改父类的参数(推荐)

    PageNumberPagination

    子类中的属性:

    如何使用:

    from rest_framework.generics import ListAPIView
    from rest_framework.pagination import PageNumberPagination
    from app01.models import Books
    from app01.ser import BooksSerializer
    
    # 第一步:
    class BookPageNumberPagination(PageNumberPagination):
        page_size = 3         # 每页条数
        page_query_param = 'page'   # 查询第几页的key
        page_size_query_param = 'size'  # 每一页显示的条数
        max_page_size = 5   # 每页最大条数
    
    
    class BookView(ListAPIView):
        queryset = Books.objects.all()
        serializer_class = BooksSerializer
        
        # 第二步:分页配置
        pagination_class = BookPageNumberPagination
        
        
    # url:http://127.0.0.1:8000/books/?page=1size=5 查询第1页,一共显示五条数据
    
    

    LimitOffsetPagination

    子类中的属性:

    如何使用:

    from rest_framework.generics import ListAPIView
    from rest_framework.pagination import LimitOffsetPagination
    from app01.models import Books
    from app01.ser import BooksSerializer
    
    # 第一步:
    class BookLimitOffsetPagination(LimitOffsetPagination):
        default_limit = 3           # 每页条数
        limit_query_param = 'limit'     # 往后拿几条
        offset_query_param = 'offset'   # 从第几条往后拿几条的标杆
        max_limit = 5       # 每页最大拿几条
    
    
    class BookView(ListAPIView):
        queryset = Books.objects.all()
        serializer_class = BooksSerializer
        
        # 第二步:分页配置
        pagination_class = BookLimitOffsetPagination
        
        
    # url:http://127.0.0.1:8000/books/?limit=3offset=4  从第三条开始往后拿4条数据
    
    

    CursorPagination

    子类中的属性:

    如何使用:

    CursorPagination的查询速度快,但是却不能定位到第几页这样查,要么往前查,要么往后查。

    from rest_framework.generics import ListAPIView
    from rest_framework.pagination import CursorPagination
    from app01.models import Books
    from app01.ser import BooksSerializer
    
    # 第一步:
    class BookCursorPagination(CursorPagination):
        cursor_query_param = 'cursor'   # 每页查询的key
        page_size = 3       # 每页显示条数
        ordering = 'id'    # 排序字段
    
    
    class BookView(ListAPIView):
        queryset = Books.objects.all()
        serializer_class = BooksSerializer
        
        # 第二步:分页配置
        pagination_class = BookCursorPagination
        
        
    # url:http://127.0.0.1:8000/books/?cursor=cD0z
    
    

    继承APIView使用方法

    像方式一,方式二这样使用的话,就要视图类是继承 ListAPIView 然后直接配置就可以了

    但是如果视图类继承的是 GenericAPIView 或者 APIView 的话,就需要用另一种方式了:

    使用方法:

    # 1、定义一个分页器
    class BookPageNumberPagination(PageNumberPagination):
        page_size = 3         # 每页条数
        page_query_param = 'page'   # 查询第几页的key
        page_size_query_param = 'size'  # 每一页显示的条数
        max_page_size = 5   # 每页最大条数
    
    
    class BookView(APIView):
    
        def get(self, request, *args, **kwargs):
            book_list = Books.objects.all()
    
            # 2、实例化得到一个分页器对象
            page_obj = BookPageNumberPagination()
            
            # 3、调用paginate_queryset返回每一页的数据
            book_list = page_obj.paginate_queryset(book_list, request, view=self)
    
            # 4、获取上一页下一页链接
            next_url = page_obj.get_next_link()
            previous_url = page_obj.get_previous_link()
    
            # 5、序列化
            book_ser = BooksSerializer(book_list, many=True)
            
            # 6、加入响应信息中
            data = {'next_url': next_url, 'previous_url': previous_url, 'data': book_ser.data}
            return Response(data=data)
    
    

    四、异常处理

    异常处理主要是用来统一接口返回

    源码分析

    异常处理在APIView的api_settings已经配置好了

    'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',

    def exception_handler(exc, context):
        # 先判断是不是404
        if isinstance(exc, Http404): # exc是异常信息的异常对象
            exc = exceptions.NotFound()
        # 然后判断是不是权限的问题
        elif isinstance(exc, PermissionDenied):
            exc = exceptions.PermissionDenied()  # 比如权限问题会返回一个字典
            
     # 在判断你抛出的是不是API的异常——>认证权限这些都是继承了API的异常
        if isinstance(exc, exceptions.APIException):
            headers = {}
            if getattr(exc, 'auth_header', None):
                headers['WWW-Authenticate'] = exc.auth_header
            if getattr(exc, 'wait', None):
                headers['Retry-After'] = '%d' % exc.wait
    
            if isinstance(exc.detail, (list, dict)):
                data = exc.detail
            else:
                data = {'detail': exc.detail}
    
            set_rollback()
            return Response(data, status=exc.status_code, headers=headers)
        # 只要是上面这些异常都做了处理
       
    
        return None  # 意味有些异常它没有处理,就会交给Django自己处理
    
    

    如何处理

    因为dir有些异常它不做处理,Django处理的又不符合我们的标准,所以就要写一个统一的异常类来替换掉它,把所有情况都处理,只要前端出异常看到的都是固定的东西。

    如何写:

    重写一个类,和它基本上差不多,配置的时候在 settings.py 里面全局配置

    #  app01_auth.py
    from rest_framework.views import exception_handler
    from rest_framework.response import Response
    
    def app01_exception_handler(exc, context):
        response = exception_handler(exc, context)  # 原来的drf处理的我们也需要
        # 两种情况,一个是None,drf没有处理,Django处理了,但是处理的不符合需求
        # response对象,drf处理了我们需要的
    
    
        if not response:
            # 如果没处理,那么我们自己处理
            return Response(data={'status': 400, 'error': str(exc)}, status=400)
        else:
            # drf 处理了,那么取出它处理的信息,重新处理一下
            return Response(data={'status': 400, 'error': response.data.get('detail')}, status=400)
    
    

    然后再全局配置一下:settings.py

    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'app01.app_auth.app01_exception_handler',
    }
    

    五、封装Response对象

    class APIResponse(Response):
        def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs):
            
            dic = {'code': code, 'msg': msg}
            
            if  data:
                dic = {'code': code, 'msg': msg,'data':data}
                
            dic.update(kwargs)
            
            super().__init__(data=dic, status=status,headers=headers)
            
            
    # 使用
    return APIResponse(data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee')
    return APIResponse(data={"name":'xiaoyang'})
    return APIResponse(code='101',msg='错误',data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee',header={})
    

    总结

    到此这篇关于DRF过滤排序分页异常处理的文章就介绍到这了,更多相关DRF过滤排序分页内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • Django实现drf搜索过滤和排序过滤
    上一篇:OpenCV 图像梯度的实现方法
    下一篇:Pandas高级教程之Pandas中的GroupBy操作
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    DRF过滤排序分页异常处理的过程记录 DRF,过滤,排序,分页,异常,