Django REST 异常处理详解


Posted in Python onJuly 15, 2020

异常

异常处理…允许错误处理在程序结构的中心或者高层级的地方被清晰有条理的组织起来。

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

更多阅读官方原文链接

以上这篇Django REST 异常处理详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python写的一个简单DNS服务器实例
Jun 04 Python
pytorch 数据集图片显示方法
Jul 26 Python
利用Python将文本中的中英文分离方法
Oct 31 Python
对Python3中bytes和HexStr之间的转换详解
Dec 04 Python
Python图像处理之直线和曲线的拟合与绘制【curve_fit()应用】
Dec 26 Python
在python tkinter中Canvas实现进度条显示的方法
Jun 14 Python
Flask框架模板渲染操作简单示例
Jul 31 Python
Python处理session的方法整理
Aug 29 Python
python处理document文档保留原样式
Sep 23 Python
django使用F方法更新一个对象多个对象字段的实现
Mar 28 Python
给ubuntu18安装python3.7的详细教程
Jun 08 Python
Django视图、传参和forms验证操作
Jul 15 Python
使用OpenCV实现道路车辆计数的使用方法
Jul 15 #Python
django restframework serializer 增加自定义字段操作
Jul 15 #Python
浅谈django不使用restframework自定义接口与使用的区别
Jul 15 #Python
浅析Python 条件控制语句
Jul 15 #Python
python中如何设置代码自动提示
Jul 15 #Python
PyTorch实现重写/改写Dataset并载入Dataloader
Jul 14 #Python
python实现将中文日期转换为数字日期
Jul 14 #Python
You might like
php urlencode()与urldecode()函数字符编码原理详解
2011/12/06 PHP
PHP5下$_SERVER变量不再受magic_quotes_gpc保护的弥补方法
2012/10/31 PHP
PHP仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(上)
2017/05/26 PHP
PHP中$GLOBALS['HTTP_RAW_POST_DATA']和$_POST的区别分析
2017/07/03 PHP
ThinkPHP整合datatables实现服务端分页的示例代码
2018/02/10 PHP
js函数的引用, 关于内存的开销
2012/09/17 Javascript
jQuery动画animate方法使用介绍
2013/05/06 Javascript
jQuery旋转木马式幻灯片轮播特效
2015/12/04 Javascript
JS/jQ实现免费获取手机验证码倒计时效果
2016/06/13 Javascript
jQuery实现的可编辑表格完整实例
2016/06/20 Javascript
Vue.js 十五分钟入门图文教程
2018/09/12 Javascript
Vue 框架之键盘事件、健值修饰符、双向数据绑定
2018/11/14 Javascript
微信小程序module.exports模块化操作实例浅析
2018/12/20 Javascript
Vuex实现数据增加和删除功能
2019/11/11 Javascript
Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式功能
2020/04/09 Javascript
Vue 如何使用props、emit实现自定义双向绑定的实现
2020/06/05 Javascript
vue video和vue-video-player实现视频铺满教程
2020/10/30 Javascript
[03:12]完美世界DOTA2联赛PWL DAY6集锦
2020/11/05 DOTA
基于wxPython的GUI实现输入对话框(2)
2019/02/27 Python
python中的协程深入理解
2019/06/10 Python
OpenCV 轮廓检测的实现方法
2019/07/03 Python
python pip安装包出现:Failed building wheel for xxx错误的解决
2019/12/25 Python
TensorFlow Saver:保存和读取模型参数.ckpt实例
2020/02/10 Python
如何基于Python代码实现高精度免费OCR工具
2020/06/18 Python
Michael Kors香港官网:美国奢侈品品牌
2019/12/26 全球购物
.NET面试题:什么是反射
2016/09/30 面试题
实习教师自我鉴定
2013/12/12 职场文书
学校安全教育制度
2014/01/31 职场文书
优良学风班申请材料
2014/02/13 职场文书
党员个人查摆剖析材料
2014/10/16 职场文书
慰问信模板
2015/02/14 职场文书
综合素质自我评价评语
2015/03/06 职场文书
2015年全国助残日活动方案
2015/05/04 职场文书
《风筝》教学反思
2016/02/23 职场文书
大学生暑期实践报告之企业经营管理
2019/08/08 职场文书
kubernetes集群搭建Zabbix监控平台的详细过程
2022/07/07 Servers