zoukankan      html  css  js  c++  java
  • drf-过滤排序异常处理封装Response对象

    一 过滤Filtering

    对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

    安装

    pip install django-filter
    注册
    
    INSTALLED_APPS = [
        ...
        'django_filters',  # 需要注册应用,
    ]

    全局配置

    REST_FRAMEWORK = {
        ...
        'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
    }
    # 在视图中添加filter_fields属性,指定可以过滤的字段
    class StudentListView(ListAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentSerializer
        filter_fields = ('age', 'sex')
    # 127.0.0.1:8000/four/students/?sex=1

    局部配置

    from django_filters.rest_framework import DjangoFilterBackend
    class StudentListView(ListAPIView):
        ...
        filter_backends = [DjangoFilterBackend,]
        filter_fields = ('age', 'sex')

    二 排序

    对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

    使用方法:

    在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

    前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

    示例:

    from rest_framework.generics import ListAPIView
    from rest_framework.filters import OrderingFilter
    from app01.models import Book
    from app01.ser import BookSerializer
    class Book2View(ListAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        filter_backends = [OrderingFilter]
        ordering_fields = ('id', 'price')
    
    #使用 
    http://127.0.0.1:8000/books2/?ordering=-price
    http://127.0.0.1:8000/books2/?ordering=price
    http://127.0.0.1:8000/books2/?ordering=-id
    -id 表示针对id字段进行倒序排序
    id  表示针对id字段进行升序排序

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

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

    三 异常处理 Exceptions

    REST framework提供了异常处理,我们可以自定义异常处理函数。

    3.1 使用方式

    from rest_framework.views import exception_handler
    
    def my_exception_handler(exc, context):
        # 先调用REST framework默认的异常处理方法获得标准错误响应对象
        response = exception_handler(exc, context)
    
        # 在此处补充自定义的异常处理
        if not response:
            if isinstance(exc, ZeroDivisionError):
                return Response(data={'status': 777, 'msg': "除以0的错误" + str(exc)}, status=status.HTTP_400_BAD_REQUEST)
            return Response(data={'status':999,'msg':str(exc)},status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST)

    在配置文件中声明自定义的异常处理

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

    3.2 案例

    补充上处理关于数据库的异常

    from rest_framework.views import exception_handler
    from rest_framework.response import Response
    from rest_framework.views import exception_handler as drf_exception_handler
    from rest_framework import status
    from django.db import DatabaseError
    
    def exception_handler(exc, context):
        response = drf_exception_handler(exc, context)
    
        if response is None:
            view = context['view']
            print('[%s]: %s' % (view, exc))
            if isinstance(exc, DatabaseError):
                response = Response({'detail': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
            else:
                response = Response({'detail': '未知错误'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
        return response
      
    # 在setting.py中配置
    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'app01.ser.exception_handler'
    }

    3.3 REST framework定义的异常

    • APIException 所有异常的父类
    • ParseError 解析错误
    • AuthenticationFailed 认证失败
    • NotAuthenticated 尚未认证
    • PermissionDenied 权限决绝
    • NotFound 未找到
    • MethodNotAllowed 请求方式不支持
    • NotAcceptable 要获取的数据格式不支持
    • Throttled 超过限流次数
    • ValidationError 校验失败

    也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。

    四 封装Response对象(重要)

    为了让放回的数据有一定的格式我们要使用自己封装的Response对象

    from rest_framework.response import 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":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee')
    return APIResponse(data={"name":'lqz'})
    return APIResponse(code='101',msg='错误',data={"name":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee',header={})
  • 相关阅读:
    (转载)你好,C++(21)只要天还没黑,就一直在工地干活-4.3.1 while循环:只要…就一直…
    (转载)你好,C++(20).4.2.2 表达并列条件选择的switch语句:如果……如果……如果……
    (转载)你好,C++(19)“老师,我这次四级考试过了没有?”——4.2 条件选择语句
    (转载)你好,C++(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序
    (转载)你好,C++(17)0.1*10不等于1.0——4.1.4 关系操作符4.1.5 逻辑操作符
    (转载)你好,C++(16)用表达式表达我们的设计意图——4.1 用操作符对数据进行运算
    (转载)你好,C++(15)四两拨千斤——3.9 指向内存位置的指针
    (转载)你好,C++(14)如何描述“一个名叫陈良乔,年龄33岁,身高173厘米,体重61.5千克的男人”——3.8 用结构体类型描述复杂的事物
    (转载)你好,C++(13)这道单选题的答案是A、B、C还是D?3.7 枚举类型
    (转载)你好,C++(12)如何管理多个类型相同性质相同的数据?3.6 数组
  • 原文地址:https://www.cnblogs.com/bk134/p/13306381.html
Copyright © 2011-2022 走看看