Django 如何全局捕获异常和DEBUG

DEBUG

默认:False

一个开启、关闭调试模式的布尔值。

永远不要在 DEBUG 开启的情况下将网站部署到生产中。

调试模式的主要功能之一是显示详细的错误页面。如果你的应用程序在 DEBUG 为 True 时引发了异常,Django 会显示一个详细的回溯,包括很多关于你的环境的元数据,比如所有当前定义的 Django 配置(来自 settings.py)。

视图抛出异常

Django 和 Django-rest-framework 中视图最终都是集成 class APIView(View),从 APIView 中查看,所有的请求都是通过 dispatch 这个方法分发:

def dispatch(self, request, *args, **kwargs):
    """
    `.dispatch()` is pretty much the same as Django's regular dispatch,
    but with extra hooks for startup, finalize, and exception handling.
    """
    self.args = args
    self.kwargs = kwargs
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

    try:
        self.initial(request, *args, **kwargs)

        # Get the appropriate handler method
        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

response = self.handle_exception(exc) 中:

    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()
        response = exception_handler(exc, context)

        if response is None:
            self.raise_uncaught_exception(exc)  # 异常部分

        response.exception = True
        return response

self.raise_uncaught_exception(exc) 中:
会通过 DEBUG 判读是否是开发模式,如果是开发模式通过 request 包装器返回,如果不是会重新抛出最近的异常。

    def raise_uncaught_exception(self, exc):
        if settings.DEBUG:
            request = self.request
            renderer_format = getattr(request.accepted_renderer, 'format')
            use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
            request.force_plaintext_errors(use_plaintext_traceback)
        raise  # 重新抛出最近的异常

全局捕获

视图抛出异常之后,怎么处理异常,如果不处理前端会抛出一个显示详细的错误页面。如果你的应用程序在 DEBUG 为 True 时引发了异常,Django 会显示一个详细的回溯,包括很多关于你的环境的元数据,比如所有当前定义的 Django 配置,暴露太多内容,对网站会非常不安全。解决办法,定义一个全局的异常捕获,如果有异常,这返回一个可视化的信息给起前端。

class AppExceptionMiddleware(MiddlewareMixin):

    def process_exception(self, request, exception):
        self.exception = exception
        self.request = request

        # 用户自我感知的异常抛出
        if isinstance(exception, BlueException):
            logger.log(
                exception.LOG_LEVEL,
                (u"""捕获主动抛出异常, 具体异常堆栈->[%s] status_code->[%s] & """
                 u"""client_message->[%s] & args->[%s] """) % (
                    traceback.format_exc(),
                    exception.ERROR_CODE,
                    exception.message,
                    exception.args
                )
            )

            response = JsonResponse(exception.response_data())

            response.status_code = exception.STATUS_CODE
            return response

        response = JsonResponse({
            "result": False,
            'code': "50000",
            'message': _(u"系统异常,请联系管理员处理"),
            'data': None
        })
        response.status_code = 500

        # notify sentry
        if sentry_exception_handler is not None:
            sentry_exception_handler(request=request)

        return response

效果

Django 如何全局捕获异常和DEBUG_第1张图片

你可能感兴趣的:(django,orm,python,django,sqlite,数据库,python,drf,后端,权限)