第七篇:DRF之异常处理和封装Response

第七篇:DRF之异常处理和封装Response

一、异常处理

1、异常处理源码分析

我们发现django的内置的异常处理,接口并不统一,并且处理的不符合我们的要求,所以,我们需要自定义一个异常处理方法,来替换掉全局的异常处理。

全局的异常处理函数可以在from rest_framework.views import exception_handler中找到。

2、异常处理使用

我们以访问频率为例子进行测试,如果在1分钟内访问3次以上,就会抛出频率限制异常。

drf内置的异常处理返回的数据并不能满足我们的要求。效果如下。

实现自定义异常处理的具体代码如下所示。

我们在settings.py中如下配置。

# 配置REST_FRAMEWORK参数
REST_FRAMEWORK = {
    # 全局配置自定义的异常处理
    "EXCEPTION_HANDLER": "app01.app_permission.my_exception_handler"
}

app_permission.py中书写自定义异常处理。

def my_exception_handler(exc, context):
    # 原来异常处理的返回【两种情况:1、drf处理过的response对象 2、None】
    old_exception_handler_response = exception_handler(exc, context)
    print(exc)  # Request was throttled. Expected available in 60 seconds.
    print(type(exc))  # <class 'rest_framework.exceptions.Throttled'>
    print(context)  # {'view': <app01.views.TestView5 object at 0x000001CB18862A20>, 'args': (), 'kwargs': {}, 'request': <rest_framework.request.Request object at 0x000001CB18862550>}
    print(type(context))  # <class 'dict'>

    # 如果drf内置进行了处理,我们进行修改处理的结果
    from rest_framework.exceptions import Throttled
    if old_exception_handler_response:
        if isinstance(exc, Throttled):
            # 返回自己自定义的结果
            return Response(
                data={
                    'status': 2000,
                    # 内置处理后的信息放在字典包裹的detail中
                    'msg': old_exception_handler.data_response.get('detail'),
                },
                status=status.HTTP_400_BAD_REQUEST
            )
    # 如果drf内置没有进行异常处理
    else:
        return Response(
            data={
                'status': 3000,
                'msg': '频率限制出现了异常' + str(exc),
            },
            status=status.HTTP_400_BAD_REQUEST
        )

由此我们可以实现异常返回信息的统一定制。

二、封装Response

因为drf提供的Response过于局限,灵活性叫差,所以在大多数情况下,我们都必须自己重新封装Response方法,来替代原生的Response。

我们进行如下封装。

# 重新封装Response对象
class CommonResponse(Response):
    def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, **kwargs):
        print(kwargs)
        # 自定义一个返回字典
        back_dic = {'code': code, 'msg': msg}
        # 如果传入数据
        if data:
            # 将数据添加进字典
            back_dic['data'] = data
        # 最后将传过来的多余键值对全部添加进字典
        back_dic.update(kwargs)
        # 调用父类Response的__init__()方法
        super().__init__(data=back_dic, status=status, headers=headers)

使用方式如下。

# 自定义的CommonResponse返回测试
class TestView6(APIView):

    def get(self, request):
        return CommonResponse(data={'name': 'yangyi', 'age': 18}, token='adfasdfasd', aa='666666')

使用效果如下所示。

posted @ 2021-07-23 11:17  YangYi215  阅读(682)  评论(0编辑  收藏  举报