drf 异常模块+响应模块
一、drf异常模块源码分析(重点)
- 在APIView的dispatch方法中,有一个超大的try...except...,将代码运行异常都交给异常处理模块处理
self.handle_exception(exc)
方法 - 从配置中映射出配置处理异常的函数(自定义异常模块就是自定义配置指向自己的函数):
self.get_exception_handler()
方法->return self.settings.EXCEPTION_HANDLER
,通过settings获取了异常处理的方法 - 默认的异常函数在和源码的
APIView
类相同的views文件中 exception_handler(exc, context)
处理异常:- 如果异常错误是404,或
APIException
这个基类中的就处理,否则就之间返回None
- 如果异常错误是404,或
注:一般异常模块我们需要重写,因为当项目上线时,我们需要捕获并记录项目运时出现的异常信息,方便修改
二、自定义配置drf异常模块
- 在settings文件的配置中配置EXCEPTION_HANDLER,指向自定义的exception_handler函数
- 当drf出现异常了,都会回调
exception_handler
函数,携带 异常对象和异常相关信息内容,在exception_handle
r函数完成异常信息的返回以及异常信息的logging日志
'''settings.py配置'''
REST_FRAMEWORK = {
# 异常模块,二选一即可
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', # 源码的异常处理函数
# 'EXCEPTION_HANDLER': 'api.utils.exception.exception_handler', # 自定义的异常处理函数
}
'''exception.py'''
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响应模块
- drf响应模块就是Response类,Response类实例化产生对象就是返回响应信息和响应状态码等。
- 因此响应模块的源码只需要看Response类的
__init__
方法就可以了
def __init__(self, data=None, status=None,template_name=None, headers=None,
exception=False, content_type=None):
'''
# data: 是返回的信息。当出现异常时,drf的异常处理函数都将异常信息封装成{'detail': exc.detail}
# status: 响应状态码。
# headers: 响应头信息
# exception: 标识异常是否发生,随便你写不写。没啥区别
# content_type: 响应类型。默认是json。drf也只能返回json格式数据
'''
3.1 二次封装Response
from rest_framework.response import Response
class APIResponse(Response):
def __init__(self, data_status=0, msg="ok", results=None, http_status=200, headers=None, exception=False, **kwargs):
# 格式化data
data = { # json的response基础有数据状态码和数据状态信息
"status":data_status,
"msg":msg
}
if results is not None: # 后台有数据,响应数据
data["results"] = results
data.update(**kwargs) # 后台的一切自定义响应数据直接放到响应数据data中
super().__init__(data=data, status=http_status, headers=headers, exception=exception)