异常模块(重点)
重写异常模块目的是记录异常信息(项目上线)
1、在settings的drf配置中配置EXCEPTION_HANDLER,指向自定义的exception_handler函数
2、异常模块:django项目的所有异常都会被处理,drf能处理的会自己处理(4xx),不能处理的交给django处理(5xx)改写exception_handler,在全局配置
2、drf出现异常了,都会回调exception_handler函数,携带 异常对象和异常相关信息内容,在exception_handler函数完成异常信息的返回以及异常信息的logging日志
核心:异常信息都需要被logging记录,所以需要自定义;drf只处理客户端异常,服务器异常需要手动处理,统一处理结果
用法
- 主要是用来记录系统的错误,方便进行修改,特别重要,出现异常就要进行记录。
- 重写异常
配置settings.py
REST_FRAMEWORK = {
# 异常
# 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',#系统异常
'EXCEPTION_HANDLER': 'api.utils.exception_handler',#重写异常
}
#测试
from rest_framework.response import Response
def exception_handler(exc, condent):
print(exc)#错误信息
print(condent)#错误来源
return Response({
'msg':"异常"
})
初级版
from rest_framework.response import Response
def exception_handler(exc, context):
# 开发阶段一定要记录日志
# logging.error(exc)
return Response('%s - %s' % (context['view'].__class__.__name__, exc))
升级版
from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exception_handler
def exception_handler(exc, context):
response = drf_exception_handler(exc, context)
if response is None: # drf没有处理的异常
response = Response({'detail': '%s' % exc})
# 项目阶段,要记录到日志文件
return response
究极版
"""
返回数据类型
response = {
'status': 7,
'exc': '异常信息'
}
"""
from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
def exception_handler(exc, context):
response = drf_exception_handler(exc, context)
if response is None: # drf没有处理的异常(服务器异常)
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR, data={
'status': 7,
'exc': '%s' % exc
})
#设置状态码
# 项目阶段,要记录到日志文件
return Response(status=response.status_code, data={
'status': 7,
# drf处理的客户端异常,原始处理方式是将异常信息放在response对象的data中,data的格式是{'datail': '具体的异常信息'}
'exc': '%s' % response.data.get('detail')
})
在使用drf的时候,验证与is_valid(raise_exception=True)冲突,因此使用
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
def exception_handler(exc, context):
# drf_exception_handler的执行结果就是异常信息的Response对象或None
# 是Response对象可以直接返回
# 是None可以从exc中拿到异常信息,从context拿到是谁出现的异常,自己格式化成Response对象返回
# 重点:自定义异常模块目的是记录异常信息到日志文件 - 产品阶段
response = drf_exception_handler(exc, context)
if response is None:
response = Response({'detail': '%s' % exc}, status=500, exception=True)
# logging.error(response.data)
return response
源码分析
1、在APIView的dispatch方法中,有一个超大的try...except...,将代码运行异常都交给异常处理模块处理self.handle_exception(exc)
2、从配置中映射出配置处理异常的函数(自定义异常模块就是自定义配置指向自己的函数):self.get_exception_handler()
3、异常函数exception_handler(exc, context)处理异常,就会走自己的:
先交给系统处理(客户端的异常),系统没处理(服务器异常),再自己处理