更新时间:2018-08-31 来源:黑马程序员技术社区 浏览量:
REST框架的视图处理了各种异常,并正确地返回了错误响应。
被处理的异常有:
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 AllowedContent-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_handlerdef 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
from rest_framework.views import exception_handle
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)
serializer.is_valid(raise_exception=True)
在generic视图中使用raise_exception=True标记,意味着你可以在你的API中全局复写校验错误响应的格式。如果你要这么做,建议你使用一个自定义的异常,上文有描述。
默认情况下,该异常返回400 Bad Request
作者:黑马程序员技术社区
首发:http://python.itheima.com/