第七篇: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')
使用效果如下所示。