REST框架视图中的异常处理
REST框架的视图处理各种异常,并处理返回适当的错误响应。
处理的异常是:
APIException
在REST框架内部引发的子类。- Django的
Http404
例外。 - Django的
PermissionDenied
例外。
在每种情况下,REST框架都会返回带有适当状态代码和内容类型的响应。响应的正文将包括有关错误性质的任何其他详细信息。
大多数错误响应都将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”键,或为该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']
。
还必须使用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
序列化程序验证失败时通用视图返回的响应。
API参考
APIException
签名: APIException()
在类或中引发的所有异常的基类。APIView``@api_view
为了提供一个自定义异常,子类APIException
和设置.status_code
,.default_detail
以及default_code
对类属性。
例如,如果您的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.'
default_code = 'service_unavailable'
检查API异常
有许多不同的属性可用于检查API异常的状态。您可以使用它们为您的项目构建自定义异常处理。
可用的属性和方法是:
.detail
-返回错误的文字描述。.get_codes()
-返回错误的代码标识符。.get_full_details()
-返回文字说明和代码标识符。
在大多数情况下,错误详细信息将很简单:
>>> print(exc.detail)
You do not have permission to perform this action.
>>> print(exc.get_codes())
permission_denied
>>> print(exc.get_full_details())
{'message':'You do not have permission to perform this action.','code':'permission_denied'}
在验证错误的情况下,错误详细信息将是项目的列表或字典:
>>> print(exc.detail)
{"name":"This field is required.","age":"A valid integer is required."}
>>> print(exc.get_codes())
{"name":"required","age":"invalid"}
>>> print(exc.get_full_details())
{"name":{"message":"This field is required.","code":"required"},"age":{"message":"A valid integer is required.","code":"invalid"}}
解析错误
签名: ParseError(detail=None, code=None)
在访问时请求包含格式错误的数据时引发request.data
。
默认情况下,此异常导致响应的HTTP状态代码为“ 400 Bad Request”。
验证失败
签名: AuthenticationFailed(detail=None, code=None)
当传入请求包含不正确的身份验证时引发。
默认情况下,此异常会导致HTTP状态码为“ 401未经身份验证”的响应,但也可能会导致“ 403禁止访问”响应,具体取决于所使用的身份验证方案。有关更多详细信息,请参见身份验证文档。
未认证
签名: NotAuthenticated(detail=None, code=None)
当未经身份验证的请求未通过权限检查时引发。
默认情况下,此异常会导致HTTP状态码为“ 401未经身份验证”的响应,但也可能会导致“ 403禁止访问”响应,具体取决于所使用的身份验证方案。有关更多详细信息,请参见身份验证文档。
没有权限
签名: PermissionDenied(detail=None, code=None)
在通过身份验证的请求未通过权限检查时引发。
默认情况下,此异常导致响应的HTTP状态代码为“ 403 Forbidden”。
未找到
签名: NotFound(detail=None, code=None)
在给定URL上不存在资源时引发。此异常等效于标准Http404
Django异常。
默认情况下,此异常导致响应的HTTP状态代码为“ 404 Not Found”。
方法不被允许
签名: MethodNotAllowed(method, detail=None, code=None)
在未映射到视图上的处理程序方法的传入请求发生时引发。
默认情况下,此异常导致响应的HTTP状态代码为“ 405 Method Not Allowed”。
不能接受的
签名: NotAcceptable(detail=None, code=None)
当传入请求发生且Accept
任何可用渲染器均无法满足的标头时引发。
默认情况下,此异常导致响应的HTTP状态代码为“ 406 Not Acceptable”。
不支持的媒体类型
签名: UnsupportedMediaType(media_type, detail=None, code=None)
在访问时没有解析器可以处理请求数据的内容类型时引发request.data
。
默认情况下,此异常导致响应的HTTP状态代码为“ 415不支持的媒体类型”。
节流的
签名: Throttled(wait=None, detail=None, code=None)
当传入请求未通过节流检查时引发。
默认情况下,此异常导致响应的HTTP状态代码为“ 429 Too Many Requests”。
验证错误
签名: ValidationError(detail, code=None)
该ValidationError
异常是从其他略有不同的APIException
类别:
- 该
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)
通用视图使用该raise_exception=True
标志,这意味着您可以在API中全局覆盖验证错误响应的样式。为此,请使用自定义异常处理程序,如上所述。
默认情况下,此异常导致响应的HTTP状态代码为“ 400 Bad Request”。
通用错误视图
Django REST框架提供了两个错误视图,适合提供通用的JSON500
服务器错误和 400
错误请求响应。(Django的默认错误视图提供HTML响应,这可能不适用于仅API的应用程序。)
根据Django的自定义错误视图文档中的说明使用它们。
rest_framework.exceptions.server_error
返回带有状态码500
和application/json
内容类型的响应。
设置为handler500
:
handler500 = 'rest_framework.exceptions.server_error'
rest_framework.exceptions.bad_request
返回带有状态码400
和application/json
内容类型的响应。
设置为handler400
:
handler400 = 'rest_framework.exceptions.bad_request'