Django REST 异常处理详解
作者:袁慎建@ThoughtWorks 发布时间:2023-06-19 02:40:34
异常
异常处理…允许错误处理在程序结构的中心或者高层级的地方被清晰有条理的组织起来。
Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure.— Doug Hellmann, Python Exception Handling Techniques
Rest框架视图中的异常处理
Exception handling in REST framework views
REST框架的视图处理了各种异常,并正确地返回了错误响应。
REST framework's views handle various exceptions, and deal with returning appropriate error responses.
被处理的异常有:
Rest框架内部抛出的APIException的子类。
Django的Http404异常。
Django的PermissionDenied异常
针对每种情况,REST框架将返回一个包含了正确的状态码和content-type的响应。响应体包含了任何关于错误本身的额外细节。
大部分的错误响应将在响应体中包含了一个detail的键。
例如下面请求:
DELETE http://api.example.com/foo/bar HTTP/1.1
Accept: application/json
你还可能接收到一个错误响应,表明对该资源DELETE方法不允许的。
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 42
{"detail": "Method 'DELETE' not allowed."}
校验错误的处理有些轻微的不同,它会把字段的名字作为键包含进来。如果校验错误没有被指定到一个特定的字段,那么它会使用non_field_errors作为键,或者是你在setting文件中设定的NON_FIELD_ERRORS_KEY任意字符串的值。
任何校验错误将类似下面的形式:
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 94
{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}
自定义异常处理
你可以实现你的自定义异常处理。可以通过创建一个异常处理函数将API视图中抛出的异常转换成响应对象。这样一来,你就可以控制你的API使用的错误响应格式。
这个异常处理函数必须传入两个参数,第一个是要处理的异常,第二个是一个包含了任何额外上下文信息(例如当前被处理的视图)的字典。该异常处理函数要么返回一个Response对象,要么在异常无法处理的时候返回None。如果返回了None,异常将会被重新抛出,最后Django会返回一个标准的HTTP 500 ‘服务器错误'的响应。
例如,你可能希望保证所有的错误响应体中都包含了HTTP状态码,像这样:
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 62
{"status_code": 405, "detail": "Method 'DELETE' not allowed."}
为了更改响应的格式,你可以编写如下的自定义异常处理函数:
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.
response = exception_handler(exc, context)
# Now add the HTTP status code to the response.
if response is not None:
response.data['status_code'] = response.status_code
return response
参数context没有被默认的异常处理器使用,但是如果你需要更多的信息,例如你想获得当前被处理的视图,它就能给你援助之手了。通过context['view']就可以获取当前视图。
同时你必须在你的settings中配置异常处理器,显式地给EXCEPTION_HANDLER设置你期望的值,例如:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
如果没有指定,'EXCEPTION_HANDLER‘默认使用的是REST框架提供的标准的异常处理器:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}
注意一点,异常处理器仅仅在响应是由抛出的异常产生时被调用。如果由视图直接返回的响应,它将不会被调用,例如HTTP_400_BAD_REQUEST响应是在序列化校验失败时由generic视图返回的,此时异常处理器就不会被调用。
API 引用
APIException
Signature: APIException()
所有在APIView类中或者@api_view抛出的异常的基类。
为了提供自定义异常,自定义个类,继承自APIException,并设置.status_code和.default_detail属性。
例如,如果你的API依赖第三方服务,这个服务有时候可能会不可用,你或许可以考虑为”503 Service Unavailable”HTTP响应码实现一个异常类,你可以这么做:
from rest_framework.exceptions import APIException
class ServiceUnavailable(APIException):
status_code = 503
default_detail = 'Service temporarily unavailable, try again later.'
ParseError
Signature: ParseError(detail=None)
在访问request.data的时候,如果请求包含了非法的数据,就会抛出该错误。
默认,该异常返回”400 Bad Request”状态码。
AuthenticationFailed
Signature: AuthenticationFailed(detail=None)
当请求包含了错误的认证信息的时候抛出。
Raised when an incoming request includes incorrect authentication.
默认情况下,该异常返回401 Unauthenticated,但是也有可能返回403 Forbidden,这取决于使用的认证模式。详细内容参考authentication documentation
NotAuthenticated
Signature: NotAuthenticated(detail=None)
当未认证的请求权限验证失败时抛出。
默认情况下,该异常返回401 Unauthenticated,但是也有可能返回403 Forbidden,这取决于使用的认证模式。详细内容参考authentication documentation
PermissionDenied
Signature: PermissionDenied(detail=None)
当一个经认证的请求在权限校验失败时抛出。
默认返回403 Forbidden
NotFound
Signature: NotFound(detail=None)
当给定的URL不存在时抛出。该异常等效于标准的DjangoHttp404异常。
默认返回404 Not Found.
MethodNotAllowed
Signature: MethodNotAllowed(method, detail=None)
在视图中没有与请求匹配的处理方法时抛出。
默认返回405 Method Not Allowed
NotAcceptable
Signature: NotAcceptable(detail=None)
当请求的接受头不满足任何可用的渲染器时抛出。
默认返回406 Not Acceptable
UnsupportedMediaType
Signature: UnsupportedMediaType(media_type, detail=None)
当访问request.data时,没有解析器来处理请求数据的内容类型时抛出。
默认返回415 Unsupported Media Type
Throttled
Signature: Throttled(wait=None, detail=None)
当请求超过最大限制时抛出。
默认返回429 Too Many Requests
ValidationError
Signature: ValidationError(detail)
ValidationError跟其他的APIException类稍微有些不同:
The ValidationError exception is slightly different from the other APIException classes:
detail参数是强制的,非可选。
detail参数可以是错误细节的列表或者字典,也可以是一个内嵌的数据结构。
约定中,你应该导入序列化器模块并使用完整描述的ValidationError格式,这是为了跟Django的内置检验错误区分开来。例如.raise serializers.ValidationError('This field must be an integer value.')
ValidationError类应该通过验证器类为序列化器和字段校验使用。它也会在调用serializer.is_valid方法,并指定了raise_exception时被抛出。
serializer.is_valid(raise_exception=True)
在generic视图中使用raise_exception=True标记,意味着你可以在你的API中全局复写校验错误响应的格式。如果你要这么做,建议你使用一个自定义的异常,上文有描述。
默认情况下,该异常返回400 Bad Request
更多阅读官方原文链接
来源:https://blog.csdn.net/ysjian_pingcx/article/details/51015718


猜你喜欢
- Python 中方法的缺省参数问题在Python中可以缺省给方法制定缺省值,但是这个缺省值在某些情况下确是和我们预期不太一致的&he
- 因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。当然,其它字段可以辅助我们在执行这些操作时消除共
- 一、数据类型在tf中,数据类型有整型(默认是int32),浮点型(默认是float32),以及布尔型,字符串。二、数据类型信息①.devic
- 我们知道,TypeScript 支持 infer 来提取类型的一部分,通过模式匹配的方式。模式匹配比如元组类型提取最后一个元素的类型:typ
- 在传统的递归中,典型的模式是,你执行第一个递归调用,然后接着调用下一个递归来计算结果。这种方式中途你是得不到计算结果,知道所有的递归调用都返
- 今天使用python计算数据相关性,但是发现计算出的表格中间好多省略号,而且也不对齐。这也太难看了。于是在程序里加了三行:pd.set_op
- LDAP(Light Directory Access Portocol)是轻量目录访问协议,基于X.500标准,支持TCP/IP。LDAP
- Python import .pyd文件时会搜索sys.path列表中的路径运行import xxx.pyd1. 'ImportEr
- 1 多线程实现多任务1.1 什么是线程? 进程是操作系统分配程序执行资源的单位,而线程
- 本文实例讲述了python中pass语句用法。分享给大家供大家参考。具体分析如下:1、空语句 do nothing2、保证格式完整3、保证语
- 声音的本质是震动,震动的本质是位移关于时间的函数,波形文件(.wav)中记录了不同采样时刻的位移。通过傅里叶变换,可以将时间域的声音函数分解
- list的话题的确不少,而且,在编程中,用途也非常多。有看官可能要问了,如果要生成一个list,除了要把元素一个一个写上之外,有没有能够让计
- 对于Linux用户而言,命令行操作我们已经非常熟悉了。与其他流行的操作系统不同,在Linux社区中,使用命令行与使用图形用户界面执行类似任务
- 与抓取预定义好的页面集合不同,抓取一个网站的所有内链会带来一个 挑战,即你不知道会获得什么。好在有几种基本的方法可以识别页面类型。通过URL
- 数据可视化是任何探索性数据分析或报告的关键步骤,它可以让我们一眼就能洞察数据集。目前有许多非常好的商业智能工具,比如Tableau、goog
- PyCharm自身提供了大量实用的快捷键,但是由于自己之前其他软件的快捷键使用习惯与此不同,这就需要在PyCharm量身DIY属于自己的快捷
- AddHeaderAddHeader 方法用指定的值添加 HTML 标题。该方法常常向响应添加新的 HTTP 标题。它并不替代现有的同名标题
- Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE
- <script type="text/javascript"> </script>
- 一、Cookie原理HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制Cookie是http消息头中的一种属性,