欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Django与DRF结合的全局异常处理方案详解

程序员文章站 2024-03-27 09:14:34
前言django 和 drf(django rest framawork) 的结合在 python 后台中经常出现的组合。对于异常的全局处理,我们系统能有一个统一的解决方案,在开发环境能看到比较全的异...

前言

django 和 drf(django rest framawork) 的结合在 python 后台中经常出现的组合。对于异常的全局处理,我们系统能有一个统一的解决方案,在开发环境能看到比较全的异常堆栈,而在生产环境能更好的给用户一个友好的提示,本文旨在提出一个统一个全局异常处理方案,仅供参考使用。

实现的目标

如果没有 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中)。

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

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

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

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

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

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

django 异常处理方案

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

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

参考代码如下:

总结

通过上述的配置,我们可以对完成 django 结合 drf 的全局异常处理,并且保留了 django 自带 admin 的异常处理策略。

在实际的环境中,我们可以通过环境变量进行有选择的日志打印和记录。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!