返回顶部
首页 > 资讯 > 后端开发 > Python >Django REST framework 异常处理
  • 313
分享到

Django REST framework 异常处理

2024-04-02 19:04:59 313人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录写在前面DRF异常处理1. DRF 常见的异常2. 自定义异常3. 使用自定义异常4. 验证结果异常处理进阶1. 修改自定义异常2. 自定义更多异常3. 新增测试接口4. 验证结

写在前面

这两天一直在思索关于 DRF 还有哪些是项目必备的而且还没有说到的基础性的知识。这不昨天写到日志相关的功能就直接想到还有异常处理相关的功能,其实在之前项目中初期是没有统一的异常捕获手段。可能是 DRF 自带的异常 能满足大多数功能,也可能是比较懒,就使用比较粗暴的方式,以状态码 500 的方式去抛出异常,然后在日志中可以看到所有的异常信息。这么做呢,代码其实是不够健壮的,前端在调用的时候莫名的 500 也是不够友好的,所以今天就补充一下异常相关的知识。

DRF异常处理

1. DRF 常见的异常

  • AuthenticationFailed/ NotAuthenticated 一般该异常状态码为"401 Unauthenticated",主要是没有登录鉴权的时候会返回,可以用在自定义登录的时候。
  • PermissionDenied 一般用在鉴权时候使用,一般状态码为"403 Forbidden"。
  • ValidationError 一般状态码为"400 Bad Request",主要是 serializers 中对字段的校验,比如对字段类型的校验、字段长度的校验以及自定义字段格式的校验。

2. 自定义异常

这里对异常的定义主要的想法来自 ValidationError,统一异常返回的格式,方便前端统一处理类似异常。

自定义异常


# 新建 utils/custom_exception.py

class CustomException(Exception):
    _default_code = 400

    def __init__(
        self,
        message: str = "",
        status_code=status.Http_400_BAD_REQUEST,
        data=None,
        code: int = _default_code,
    ):

        self.code = code
        self.status = status_code
        self.message = message
        if data is None:
            self.data = {"detail": message}
        else:
            self.data = data

    def __str__(self):
        return self.message

自定义异常处理


# utils/custom_exception.py
from rest_framework.views import exception_handler

def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    
    # 这里对自定义的 CustomException 直接返回,保证系统其他异常不受影响
    if isinstance(exc, CustomException):
        return Response(data=exc.data, status=exc.status)
    response = exception_handler(exc, context)
    return response

配置自定义异常处理类


REST_FRAMEWORK = {
    # ...
    "EXCEPTION_HANDLER": "utils.custom_exception.custom_exception_handler",
}

3. 使用自定义异常

使用之前文章的接口用来测试自定义异常的处理


class ArticleViewSet(viewsets.ModelViewSet):
    """
    允许用户查看或编辑的api路径。
    """
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    @action(detail=False, methods=["get"], url_name="exception", url_path="exception")
    def exception(self, request, *args, **kwargs):
        # 日志使用 demo
        logger.error("自定义异常")
        raise CustomException(data={"detail": "自定义异常"})

4. 验证结果


$ curl -H 'Accept: application/JSON; indent=4' -u admin:admin http://127.0.0.1:8000/api/article/exception/
{
    "detail": "自定义异常"
}

异常处理进阶

上面的代码虽说是可以满足90%的需求,但是错误的定义太泛泛。难以集中定义管理错误,与常见项目中自定义的异常比较优点就是灵活,但是随着代码中抛出的异常越来越多加之散落在各个角落,不利于更新维护。所以下面对修改一下代码,对异常有统一的定义,同时也支持自定义返回HTTP状态码。

1. 修改自定义异常


# utils/custom_exception.py

class CustomException(Exception):
    # 自定义code
    default_code = 400
    # 自定义 message
    default_message = None

    def __init__(
            self,
            status_code=status.HTTP_400_BAD_REQUEST,
            code: int = None,
            message: str = None,
            data=None,
    ):
        self.status = status_code
        self.code = self.default_code if code is None else code
        self.message = self.default_message if message is None else message

        if data is None:
            self.data = {"detail": self.message, "code": self.code}
        else:
            self.data = data

    def __str__(self):
        return str(self.code) + self.message

2. 自定义更多异常


class ExecuteError(CustomException):
    """执行出错"""
    default_code = 500
    default_message = "执行出错"


class UnKnowError(CustomException):
    """执行出错"""
    default_code = 500
    default_message = "未知出错"

3. 新增测试接口


class ArticleViewSet(viewsets.ModelViewSet):
    """
    允许用户查看或编辑的API路径。
    """
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    @action(detail=False, methods=["get"], url_name="exception", url_path="exception")
    def exception(self, request, *args, **kwargs):
        # 日志使用 demo
        logger.error("自定义异常")
        raise CustomException(data={"detail": "自定义异常"})

    @action(detail=False, methods=["get"], url_name="unknown", url_path="unknown")
    def unknown(self, request, *args, **kwargs):
        # 日志使用 demo
        logger.error("未知错误")
        raise UnknownError()

    @action(detail=False, methods=["get"], url_name="execute", url_path="execute")
    def execute(self, request, *args, **kwargs):
        # 日志使用 demo
        logger.error("执行错误")
        raise ExecuteError()

4. 验证结果


curl -H 'Accept: application/json; indent=4' -u admin:admin http://127.0.0.1:8000/api/article/unknown/
{
    "detail": "未知出错",
    "code": 500
}
$ curl -H 'Accept: application/json; indent=4' -u admin:admin http://127.0.0.1:8000/api/article/execute/
{
    "detail": "执行出错",
    "code": 500
}

总结

需要注意自定义的异常处理函数需要在处理完成自定义异常后继续执行 rest_framework.views.exception_handler,因为这里的执行仍然需要兼容已有的异常处理;下面贴一下 DRF 有关的异常处理逻辑。

该处理函数默认处理 APIException以及 Django 内部的 Http404 PermissionDenied,其他的异常会返回 None ,会触发 DRF 500 的错误。


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

参考资料

Django REST framework 异常文档
Django 异常文档

到此这篇关于Django REST framework 异常处理的文章就介绍到这了,更多相关Django REST framework 异常内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Django REST framework 异常处理

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

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

猜你喜欢
  • Django REST framework 异常处理
    目录写在前面DRF异常处理1. DRF 常见的异常2. 自定义异常3. 使用自定义异常4. 验证结果异常处理进阶1. 修改自定义异常2. 自定义更多异常3. 新增测试接口4. 验证结...
    99+
    2024-04-02
  • Django REST Framework该怎么理解
    今天就跟大家聊聊有关Django REST Framework该怎么理解,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1.Django REST framework框架介绍Djang...
    99+
    2023-06-02
  • django rest framework http status code
    判断请求是否成功,可以从返回的状态码来区别,所以当写接口的时候也要这样做,标准化.from rest_framework import status通过导入status,里面已经定义好了状态码,源码如下:"""...
    99+
    2023-01-31
    framework rest django
  • REST Framework 处理一个超
    翻译: 不正确的配置 无法使用视图名称“snippet-detail”解析超链接关系的URL。您可能没有在API中包含相关的模型,或者在该字段上错误地配置了' lookup field '属性。 找到对应的视图所调用的超链接序列化类...
    99+
    2023-01-31
    REST Framework
  • Django REST framework 限流功能的使用
    目录正文开始 1. DRF 中的限流 2. 限流进阶配置 3. 限流思路分析 4. 源码分析 5. 其它注意事项 参考资料 正文开始 先说一个限流这个概念,最早接触这个概念是在前端...
    99+
    2024-04-02
  • django rest framework之请求与响应(详解)
    前言:在上一篇文章,已经实现了访问指定URL就返回了指定的数据,这也体现了RESTful API的一个理念,每一个URL代表着一个资源。当然我们还知道RESTful API的另一个特性就是,发送不同的请求动...
    99+
    2022-06-04
    详解 django rest
  • 深度解析Django REST Framework 批量操作
    目录DRF基本情况自定义批量操作批量创建批量删除批量更新djangorestframework-bulk依赖安装范例路由测试DRF3相关注意事项源码解读我们都知道Django res...
    99+
    2024-04-02
  • Django rest framework如何自定义用户表
    目录说明1. Django项目和应用创建2. 自定义User表3. 序列化和路由3. DRF配置4. 同步数据库5. 测试6. 命令行注册用户说明 Django 默认的用户表 aut...
    99+
    2024-04-02
  • Django REST Framework 批量操作的示例分析
    这篇文章将为大家详细讲解有关Django REST Framework 批量操作的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。DRF基本情况我们以下面的代码作为例子:models:from&nb...
    99+
    2023-06-15
  • Django rest framework自定义用户表的方法
    这篇文章主要介绍了Django rest framework自定义用户表的方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。说明Django 默认的用户表 auth_user...
    99+
    2023-06-15
  • Django Rest Framework实现身份认证源码详解
    目录一.Django框架二.身份认证的两种实现方式:三.身份认证源码解析流程一.Django框架 Django确实是一个很强大,用起来很爽的一个框架,在Rest Framework中...
    99+
    2024-04-02
  • Django RestFramework 全局异常处理详解
    目录RESTframework定义的异常一、定义异常处理类二、注册DRF框架中默认的错误处理为自己定义的类总结REST framework定义的异常 APIException 所有异...
    99+
    2024-04-02
  • 异常--python异常处理
    --****--python 异常处理------------------------------------------------------------------------------****DB API中定义了一些数据库操作的错...
    99+
    2023-01-31
    异常 python
  • 异常处理
      程序中有两种错误     1.语法错误(这种错误,根本过不了Python解释器的语法检测,必须在程序执行前就改正) #错误示范一 if #错误示范二 print("adad" 语法错误     2.逻辑错误 # 用...
    99+
    2023-01-30
    异常
  • PHP异常处理:处理异步操作中的异常
    处理异步操作中的 php 异常需要:协程中,使用 try-catch-finally 语法捕获异常。promise 中,使用 then() 和 catch() 方法处理异常。实战案例:使...
    99+
    2024-05-14
    异常处理 异步处理 swoole
  • Java JSP 异常处理:处理错误和异常
    异常处理在 Java 和 JSP 编程中至关重要,因为它允许应用程序优雅地处理错误和异常情况,从而提高健壮性和用户体验。 JSP 中的异常处理 JSP 提供了三种主要机制来处理异常: page 指令:该指令指定处理某个页面上所有未处理异...
    99+
    2024-03-15
    JSP
  • python中通过Django捕获所有异常的处理
    目录概述Django统一异常处理统一异常处理具体设计自定义异常模块自定义状态码枚举类响应信息统一结果的封装完善统一异常处理逻辑应用场景注册校验源代码尾语概述 在项目中统一异常处理,可...
    99+
    2024-04-02
  • oracle异常处理
    语句执行过程中,由于各种原因使得语句不能正常执行,可能会造成更大错误或整个系统的崩溃,所以PS/SQL提供了异常(exception)着一处理的方法来防止此类情况的发生。在代码运行的过程中无论何时发生错误,PL/SQL都能控制程序...
    99+
    2016-06-04
    oracle异常处理
  • emqx异常处理
    启动异常 通过解压tar压缩包安装后通过 ./bin/emqx start 启动报错 WARNING: Default (insecure) Erlang cookie is in use. W...
    99+
    2023-10-10
    服务器 运维
  • SpringMVC异常处理
    8.SpringMVC异常处理 1.1 异常处理的思路 系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段...
    99+
    2023-09-01
    spring java mybatis
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作