iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何使用Django与DRF实现全局异常处理方案
  • 417
分享到

如何使用Django与DRF实现全局异常处理方案

2023-06-29 06:06:26 417人浏览 泡泡鱼
摘要

小编给大家分享一下如何使用Django与DRF实现全局异常处理方案,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!实现的目标如果没有 DRF,我们只需要在 Djan

小编给大家分享一下如何使用Django与DRF实现全局异常处理方案,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

实现的目标

如果没有 DRF,我们只需要在 DjanGo 中加一个中间件就可以解决全局异常的处理问题,但是 DRF 会帮我们处理一些异常并自动返回到客户端,因此我们要协调两者的异常处理策略。

同时我们希望能使用 Django 的 admin 进行一些后台的数据查看和修改,因此最好要保留 admin 的内部异常处理行为。

本文的目标如下:

  • 保留 Django 自带的 admin 的异常处理行为

  • 拦截 DRF 的异常并进行全局异常行为处理

  • 拦截除 DRF 的异常之外的其他 Django 异常并进行全局异常行为处理

DRF 全局异常拦截的解决思路

首先 DRF 的异常都是继承自 apiException 这个类的,并且 DRF 跑出的异常会被 exception_handler 这个异常处理函数拦截(这个函数的位置在 /python3.7/site-packages/rest_framework/views.py中)。

我们进一步查看这个函数的源码:

def exception_handler(exc, context):    """    Returns the response that should be used for any given exception.    By default we handle the REST framework `APIException`, and also    Django's built-in `Http404` and `PermissionDenied` exceptions.    Any unhandled exceptions may return `None`, which will cause a 500 error    to be raised.    """    if isinstance(exc, Http404):        exc = exceptions.NotFound()    elif isinstance(exc, PermissionDenied):        exc = exceptions.PermissionDenied()    if isinstance(exc, exceptions.APIException):        headers = {}        if getattr(exc, 'auth_header', None):            headers['WWW-Authenticate'] = exc.auth_header        if getattr(exc, 'wait', None):            headers['Retry-After'] = '%d' % exc.wait        if isinstance(exc.detail, (list, dict)):            data = exc.detail        else:            data = {'detail': exc.detail}        set_rollback()        return Response(data, status=exc.status_code, headers=headers)    return None

通过这个函数的文档签名我们知道,DRF 会处理所有继承自 APIException 的异常类,并且还会额外的处理 Django 内置的 Http404 和 PermissionDenied 异常,并将这些异常的处理结果返回到前台。

如果不再这些处理范围之内,函数会返回 None,这时候会给 Django 抛出一个 500 的服务器错误异常。

DRF 支持单独配置异常处理函数,因此第一步现在 setting 中指定自定义的异常处理函数的位置:

REST_FRAMEWORK = {    'EXCEPTION_HANDLER': 'server.exception.exception_globe.globe_exception_handler'}

然后我们定义自己的异常处理程序:

第一步,调用 DRF 自己的异常处理函数第二步,对 DRF 拦截的异常进行处理第三步,将其他异常抛给 Django 处理

def globe_exception_handler(exc, context):    """        Below is the global exception handler of drf        Http404 / PermissionDenied / APIException    """    # Call REST framework's default exception handler    response = exception_handler(exc, context)    request = context['request']    # Exceptions fORM DRF and Django built-in `Http404` and `PermissionDenied`    if response is not None:        if isinstance(response.data, list):            msg = '; '.join(response.data)        elif isinstance(response.data, str):            msg = response.data        else:            msg = 'Sorry, we make a mistake (* ̄︶ ̄)!'        ex_data = {            "msg": msg,            "error_code": 1000,            "request": request.path        }        return JSONResponse(data=ex_data, status=response.status_code)    # Exceptions from others    # 如果 response 为 None 则直接触发上面的 ExceptionGlobeMiddleware    return response

Django 异常处理方案

从上一步的结果我们知道,DRF 处理不了的异常我们抛给了 Django,而 Django 支持通过定义中间件进行全局异常处理,因此接下来我们只需要定一个 Django 全局异常处理的中间件,并将中间件配置到 setting 文件中的 MIDDLEWARE 数组即可。

try:    from django.utils.deprecation import MiddlewareMixin  # Django 1.10.xexcept ImportError:    MiddlewareMixin = object  # Django 1.4.x - Django 1.9.xclass ExceptionGlobeMiddleware(MiddlewareMixin):    """        Below is the global exception handler of django    """    def process_exception(self, request, exception):        # 直接抛出 django admin 的异常        if str(request.path).startswith('/admin/'):            return None        # 捕获其他异常,直接返回 500        ex_data = {            "msg": "Sorry, we make a mistake (* ̄︶ ̄)!",            "error_code": 1000,            "request": request.path        }        return jsonResponse(data=ex_data, status=500)

值得注意的是,我们可以在中间件的处理函数中拿到 request 对象,因此,我们可以通过这个对象拿到用户请求的 url,这样,我们通过判断 url 就可以得到那些请求是来自 Django 自带的 admin 的。

参考代码如下:

# 直接抛出 django admin 的异常if str(request.path).startswith('/admin/'):    return None

以上是“如何使用Django与DRF实现全局异常处理方案”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: 如何使用Django与DRF实现全局异常处理方案

本文链接: https://www.lsjlt.com/news/323218.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作