zoukankan      html  css  js  c++  java
  • 异常模块的使用

    异常模块的使用

    重写异常模块的目的是记录异常信息(日志记录)

    一、异常模块的使用

    # 1. 配置异常模块,通过settings.py获取
    REST_FRAMEWORK = {  
        # 异常模块配置
        # Exception handling
        # 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', # 默认
        'EXCEPTION_HANDLER': 'api.utils.exception_handler', # 自己重写的路径
        'NON_FIELD_ERRORS_KEY': 'non_field_errors',
    
    }
    
    # 2.编写异常模块,创建一个新的文件.py重写exception_handler方法
    from rest_framework.response import Response
    def exception_handler(exc, context):
        # 在exception_handler函数完成异常信息的返回以及异常信息的logging日志
        print(exc)
        print(context)
        print(type(exc))
        # exc.detail 携带错误的信息
        return Response(f'{context["view"].__class__.__name__}{exc}')
    
    # 2.2升级版
    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": f'{context["view"].__class__.__name__}{exc}'})
        # 项目阶段,将日志记录保存到文件中
        return response
    
    # 2.3终极版
    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没有处理的异常
    
            response = Response(data={
                'status': 7,
                "detail": f'{context["view"].__class__.__name__}{exc}',
            },
                                status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        response = Response(status=response.status_code, data={
            'status': 7,
            "detail": f'{response.data.get("detail")}',
        })
        # 项目阶段,将日志记录保存到文件中
        return response
    
    

    二、异常源码分析

     # 1. 异常出错
         def dispatch(self, request, *args, **kwargs):
            # 记录一下有名无名分组数据
            self.args = args
            self.kwargs = kwargs
            # 二次封装request:
            # 1)将wsgi的request放在 _request 属性中
            # 2)内部还处理了数据解析,放在 parsers 属性中
            # 3)内部还处理了认证器们,放在 authenticators 属性中
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request  # 记录一下请求对象
            self.headers = self.default_response_headers  # 记录以下默认响应头
            try:
                self.initial(request, *args, **kwargs)  # 三大认证
                # 请求方式反射出具体的请求方法
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
                response = handler(request, *args, **kwargs)  # 请求方法处理请求
            except Exception as exc:
                response = self.handle_exception(exc)  # 异常模块
            self.response = self.finalize_response(request, response, *args, **kwargs)  # 二次处理响应:内部完成的多种结果的渲染方式
            return self.response  # 响应对象完成后台响应
    
    # 2 异常处理
    def handle_exception(self, exc):
        """
            Handle any exception that occurs, by returning an appropriate response,
            or re-raising the error.
            """
        if isinstance(exc, (exceptions.NotAuthenticated,
                            exceptions.AuthenticationFailed)):
            # WWW-Authenticate header for 401 responses, else coerce to 403
            auth_header = self.get_authenticate_header(self.request)
    
            if auth_header:
                exc.auth_header = auth_header
            else:
                exc.status_code = status.HTTP_403_FORBIDDEN
            # 都会走,获取异常处理函数
            exception_handler = self.get_exception_handler()
            # 获取请求数据内容字典
            context = self.get_exception_handler_context()
            # 异常函数:接收exc,context,返回response对象
            response = exception_handler(exc, context)
    
            if response is None:
                # 异常函数如果为空交给原生django处理
                self.raise_uncaught_exception(exc)
                # 异常返回
                response.exception = True
                return response
        # 2.1获取异常处理函数具体函数,可以自己配置
     def get_exception_handler(self):
            """
            Returns the exception handler that this view uses.
            """
            return self.settings.EXCEPTION_HANDLER
    

    总结:

    1. 在APIView的dispatch方法中,有一个try...except...异常,将代码运行的异常都交给异常处理模块进行处理: response = self.handle_exception(exc)
    2. 在handle_exception()中从配置中映射处理异常的函数(自定义异常模块就是自定义配置函数指向自己的函数),通过self.get_exception_handler()去获取配置文件中异常函数对象,然后将数据给自己写的函数进行处理,如果没有配置则是框架中默认的
    3. 异常函数exception_handler(exe,content)处理异常,就会走自己重写的异常函数,先交给系统处理(客户端的异常),系统没处理(服务器异常),再自己处理
    4. 核心:异常信息都需要被logging记录,所以需要自定义;drf只处理客户端异常,服务器异常需要手动处理,统一处理结果
  • 相关阅读:
    牛客(4) 重建二叉树
    牛客(3)从尾到头打印链表
    牛客(2)字符串替换
    牛客(1)二分查找
    同义词+序列+视图+临时表
    用户+授权
    控制文件+日志文件
    oracle表的基本操作
    Linux(CentOS6.8)配置Redis
    Linux(CentOS6.8)配置ActiveMQ
  • 原文地址:https://www.cnblogs.com/randysun/p/12291579.html
Copyright © 2011-2022 走看看