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

注:一般异常模块我们需要重写,因为当项目上线时,我们需要捕获并记录项目运时出现的异常信息,方便修改

二、自定义配置drf异常模块

  • 在settings文件的配置中配置EXCEPTION_HANDLER,指向自定义的exception_handler函数
  • 当drf出现异常了,都会回调exception_handler函数,携带 异常对象和异常相关信息内容,在exception_handler函数完成异常信息的返回以及异常信息的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)
posted @ 2020-04-10 11:45  小芒果测开笔记  阅读(215)  评论(0编辑  收藏  举报