Django Rest Framework 全局异常处理

在这里插入图片描述

在Django Rest Framework(DRF)中,全局异常处理是一种重要的机制,它可以帮助我们更好地管理API中的异常情况,并返回统一的错误响应。本文将详细介绍两种全局异常处理的方法:使用中间件(Middleware)和使用DRF内置的异常处理机制(ExceptionHandler)。

1. 使用中间件进行异常处理

中间件是Django中的一个通用概念,它可以用于全局性的请求和响应处理。我们可以通过自定义中间件来捕获API请求中的异常,并返回统一的错误响应。

步骤1:配置中间件

首先,在项目的settings.py文件中添加我们自定义的异常处理中间件。

# settings.py
MIDDLEWARE = [
    # ...
    # 异常处理中间件
    'utils.middleware.ExceptionMiddleware',
]

步骤2:自定义中间件

然后,在utils/middleware.py文件中定义我们的异常处理中间件。

# utils/middleware.py
import logging
from django.db import DatabaseError
from django.http.response import JsonResponse
from django.http import HttpResponseServerError
from django.middleware.common import MiddlewareMixin
from rest_framework import status
from rest_framework.response import Response
from utils.enums import *
from utils.exceptions import *
from utils.result import R
logger = logging.getLogger('django')
class ExceptionMiddleware(MiddlewareMixin):
    """统一异常处理中间件"""
    def process_exception(self, request, exception):
        """
        统一异常处理
        :param request: 请求对象
        :param exception: 异常对象
        :return:
        """
        if isinstance(exception, BusinessException):
            # 业务异常处理
            data = R.set_result(exception.enum_cls).data()
            return JsonResponse(data)
        elif isinstance(exception, DatabaseError):
            # 数据库异常
            r = R.set_result(StatusCodeEnum.DB_ERR)
            logger.error(r.data(), exc_info=True)
            return HttpResponseServerError(StatusCodeEnum.SERVER_ERR.errmsg)
        elif isinstance(exception, Exception):
            # 服务器异常处理
            r = R.server_error()
            logger.error(r.data(), exc_info=True)
            return HttpResponseServerError(r.errmsg)
        return None

步骤3:自定义异常类和状态码枚举

utils/exceptions.pyutils/enums.py文件中,我们可以定义自己的异常类和状态码枚举类。

# utils/exceptions.py
class CommonException(Exception):
    """公共异常类"""
    def __init__(self, enum_cls):
        self.code = enum_cls.code
        self.errmsg = enum_cls.errmsg
        self.enum_cls = enum_cls  # 状态码枚举类
        super().__init__()
class BusinessException(CommonException):
    """业务异常类"""
    pass
class APIException(CommonException):
    """接口异常类"""
    pass
# utils/enums.py
class StatusCodeEnum(Enum):
    """状态码枚举类"""
    OK = (0, '成功')
    ERROR = (-1, '错误')
    SERVER_ERR = (500, '服务器异常')
    # ... 其他状态码

步骤4:响应信息封装

utils/result.py文件中,我们可以定义一个统一项目信息返回结果类。

# utils/result.py
class R(object):
    """
    统一项目信息返回结果类
    """
    def __init__(self):
        self.code = None
        self.errmsg = None
        self._data = dict()
    @staticmethod
    def ok():
        """
        组织成功响应信息
        :return:
        """
        r = R()
        r.code = StatusCodeEnum.OK.code
        r.errmsg = StatusCodeEnum.OK.errmsg
        return r
    @staticmethod
    def error():
        """
        组织错误响应信息
        :return:
        """
        r = R()
        r.code = StatusCodeEnum.ERROR.code
        r.errmsg = StatusCodeEnum.ERROR.errmsg
        return r
    @staticmethod
    def server_error():
        """
        组织服务器错误信息
        :return:
        """
        r = R()
        r.code = StatusCodeEnum.SERVER_ERR.code
        r.errmsg = StatusCodeEnum.SERVER_ERR.errmsg
        return r
    @staticmethod
    def set_result(enum):
        """
        组织对应枚举类的响应信息
        :param enum: 状态枚举类
        :return:
        """
        r = R()
        r.code = enum.code
        r.errmsg = enum.errmsg
        return r
    def data(self, key=None, obj=None):
        """统一后端返回的数据"""
        if key:
            self._data[key] = obj
        context = {
            'code': self.code,
            'errmsg': self.errmsg,
            'data':self._data
        }
        return context

步骤5:测试视图

最后,在视图中抛出我们自定义的异常,以测试我们的异常处理机制是否有效。

# views.py
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from utils.enums import StatusCodeEnum
from utils.exceptions import *
class TestView(APIView):
    @api_view(['POST'])
    def verify_params(request):
        """
        校验注册信息
        :param request: 注册请求对象
        :return: response_ret
        """
        # 接受参数
        params = get_parameter_dic(request)
        username = params.get('username')
        mobile = params.get('mobile')
        # 校验参数
        all_args = [username, mobile]
        if not all(all_args):
            raise BusinessException(StatusCodeEnum.PARAM_ERR)
        # 用户名 5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}', username):
            raise BusinessException(StatusCodeEnum.USER_ERR)
        # 手机号合法性
        if not mobile:
            raise BusinessException(StatusCodeEnum.MOBILE_ERR)
        return Response("成功", status=status.HTTP_200_OK)

2. 使用ExceptionHandler进行异常处理

除了使用中间件,我们还可以使用DRF内置的异常处理机制(ExceptionHandler)来处理API中的异常。

步骤1:自定义异常处理函数

首先,在utils/exceptions.py文件中定义我们的自定义异常处理函数。

# utils/exceptions.py
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)
    if response is not None:
        response.data['status_code'] = response.status_code
    elif isinstance(exc, Exception):
        response = Response("其它异常")
    return response

步骤2:配置ExceptionHandler

然后,在项目的settings.py文件中配置我们自定义的异常处理函数。

# settings.py
REST_FRAMEWORK = {
    # 统一异常处理
    'EXCEPTION_HANDLER': 'utils.exception.custom_exception_handler'
}

这样,当API中发生异常时,就会调用我们自定义的异常处理函数,并返回统一的错误响应。
以上就是在Django Rest Framework中进行全局异常处理的两种方法。我们可以根据项目的具体需求选择合适的方法来实现异常处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/629882.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins 忘记登录密码怎么办

在安装Jenkins中遇到忘记登录密码该怎么呢?下面是一个解决办法 1. 先停止jenkins服务 我是用tomcat启动的jenkis 2. 找到config.yaml文件 find / -name config.xml命令执行后找到如下结果: /root/.jenkins/config.xml /root/.jenkins/users/admin_839…

现在适合进入AIGC行业吗?

现在适合进入AIGC行业吗? 随着人工智能生成内容(AIGC)技术的快速发展,越来越多的人开始关注这个行业。那么,现在是否是进入AIGC行业的好时机呢?本文将从行业前景、市场需求以及个人选择与规划三个方向进行…

3D轻量化引擎HOOPS Communicator在PLM全生命周期管理中的应用

在当今快速发展的工业领域,产品生命周期管理(PLM)是确保产品从设计到市场再到最终退役过程中信息一致性和流程效率的关键。 随着3D模型的日益复杂化和数据量的不断增长,传统的PLM系统面临着数据管理和渲染效率的挑战。HOOPS Comm…

【Spring之依赖注入】2. Spring处理@Async导致的循环依赖失败问题

使用异步Async注解后导致的循环依赖失败详解 1 问题复现1.1 配置类1.2 定义Service1.3 定义Controller1.4 启动springboot报错 2.原因分析:看Async标记的bean注入时机2.1 循环依赖生成过程2.2 自检程序 doCreateBean方法 3.解决方案3.1 懒加载Lazy3.1.1 将Lazy写到A…

SDL系列(一)—— 小白入门

SDL ( Simple DirectMedia Layer ) 是一套开放源代码的 跨平台多媒体开发库 ,使用 C 语 言写成。 SDL 提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的 代码就可以开发出 跨多个平台( Linu…

公共字段填充(AOP的使用)

Thread是线程池,ThreadLocal是线程变量,每个线程变量是封闭的,与其它线程变量分隔开来,在sky-common下的com.sky.context包下有一个Basecontext类 public class BaseContext {//每一个上下文创建了一个线程变量,用来存储long类型的id//创建三个方法,用来设置,取用,删除idpubli…

基于微信小程序+JAVA Springboot 实现的【房屋租赁管理系统】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称: 基于微信小程序的房屋租赁管理系统 在本次项目开发中,我们成功构建了一款基于微信小程序的房屋租赁管理系统,旨在通过现代化信息技术提升房屋租赁服务的效率和质量。以下是对本项目的全面总结: 项目背景与目…

07-Fortran基础--Fortran指针(Pointer)的使用

07-Fortran基础--Fortran指针Pointer的使用 0 引言1 指针(Poionter)的有关内容1.1 一般类型指针1.2 数组指针1.3 派生类(type)指针1.4 函数指针 2 可运行code 0 引言 Fortran是一种广泛使用的编程语言,特别适合科学计算和数值分析。Fortran 9…

43k Star!推荐一款功能强大的开源笔记软件!

程序员的公众号:源1024,获取更多资料,无加密无套路! 最近整理了一份大厂面试资料《史上最全大厂面试题》,Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

【2024系统架构设计】回顾历史,查缺补漏篇 ③

前言 hello,大家好: 💡💡💡 我们一起来备考软考高级系统架构设计师吧,本专栏提供综合知识、案例科目、论文(论点和部分示例范文)等内容,包括知识点总结和记忆小妙招哦。 🚀🚀🚀 可以减少资料查找和收集的时间,提高效率,我们一起集中精力学习干货吧! 💡…

Lora训练Windows[笔记]

一. 使用kohya_ss的GUI版本(https://github.com/bmaltais/kohya_ss.git) 这个版本跟stable-diffusion-webui的界面很像,只不过是训练模型专用而已,打开的端口同样是7860。 1.双击setup.bat,选择1安装好xformers,pytorch等和cuda…

Linux进程概念总结

这里总结下Linux进程概念总结❗ 冯诺依曼: CPU 运算器与控制器RAM 内存(存储器)Cache 缓存(一种技术)不属于冯诺依曼体系结构。ROM 磁盘(输入输出设备)磁盘 既可以从硬盘读取数据也可以向硬盘…

【全开源】JAVA语聊大厅语音聊天APP系统源码

语聊大厅语音聊天源码:打造专属的语音社交平台 核心功能 多人语音聊天:支持多人同时在线语音聊天,用户可以创建或加入不同的聊天室,与好友或陌生人进行实时互动。语音转文字:提供语音转文字功能,方便用户…

你好 GPT-4o!

你好 GPT-4o! OpenAI公司宣布推出 GPT-4o,这是OpenAI的新旗舰模型,可以实时对音频、视觉和文本进行推理。 GPT-4o(“o”代表“o​​mni”)是迈向更自然的人机交互的一步——它接受文本、音频、图像和视频的任意组合作…

C++二叉搜索树搜索二叉树二叉排序树

C二叉搜索树 1. 二叉搜索树的概念 二叉搜索树(BST,Binary Search Tree),也称为二叉排序树或二叉查找树。它与一般二叉树的区别在于:每个结点必须满足“左孩子大于自己,右孩子小于自己”的规则。在这种规则的约束下,二…

海上定位测量难?千寻星基稳如“定”海神针_0416(update-2)

海上定位测量难?千寻星基稳如“定”海神针 近年来,随着海洋资源的开发和利用,海上定位测量的需求日益增加,它通过测量物体的位置和方向来确定海洋中的各项活动。其准确性和可靠性对于确保海上作业的安全和效率至关重要。 由于海…

想做好抖店?新手、老玩家切勿掉进这些坑,操作要慎重!

大家好,我是电商花花。 很多人都说做抖音小店不需要脑子,会抄就行,难道做店真的就是这样吗? 真的就是会抄,会简单选品,找一些达人就能出单,就能实现睡后收入了吗? 其实并不见得&a…

Latex问题1

问题 添加bib文件的引用后 \bibliographystyle{IEEEtran} \bibliography{IEEEabrv}之后,出现莫名其妙的错误,如下 IEEEabrv.bib是我的参考文献的bib文件,CCS_1.tex是我的tex文件,bib文件中的内容为 ARTICLE{1,author{Capponi,…

精选合作伙伴:如何挑选最适合您小程序商城开发的软件公司

在选择一家合适的软件公司来协助您开发并运营小程序商城时,选择过程无疑是一项关键而复杂的任务。市场上的软件公司繁多,各具特色,那么,如何在这众多的选择中找到最适合您的合作伙伴呢?以下将从需求梳理、公司实力评估…

jiebaNET中文分词器

最近我接手了一个有趣的需求,需要对用户评价进行分词,进行词频统计和情绪分析,并且根据词频权重制成词云图以供后台数据统计,于是我便引入了jieba分词器,但是我发现网上关于jiebaNET相关文档实在太少了,甚至连配置文件…