如何在 django rest 框架中覆盖异常消息

Joh*_*aff 8 python django django-rest-framework

我正在使用基于 Django 类的视图和休息框架

object = self.get_object()
Run Code Online (Sandbox Code Playgroud)

在详细视图中,如果对象不存在并且我确实收到了类似的请求

/user/10
Run Code Online (Sandbox Code Playgroud)

然后我得到这个回应

{"detail": "not found"}
Run Code Online (Sandbox Code Playgroud)

现在我想自定义该响应

喜欢

try:
   obj = self.get_object()
except:
   raise Exception("This object does not exist")
Run Code Online (Sandbox Code Playgroud)

但这不起作用

Rah*_*pta 8

我们可以实现一个自定义异常处理函数,在对象不存在的情况下返回自定义响应。

如果对象不存在,Http404则会引发异常。因此,我们将检查是否引发了异常Http404,如果是这种情况,我们将在响应中返回我们的自定义异常消息。

from rest_framework.views import exception_handler
from django.http import Http404

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)

    if isinstance(exc, Http404):  
        custom_response_data = { 
            'detail': 'This object does not exist.' # custom exception message
        }
        response.data = custom_response_data # set the custom response data on response object

    return response
Run Code Online (Sandbox Code Playgroud)

定义自定义异常处理程序后,我们需要将此自定义异常处理程序添加到我们的 DRF 设置中。

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
Run Code Online (Sandbox Code Playgroud)


JPG*_*JPG 6

你可以如下创建一个自定义异常类,这将提高APIExceptioncustom messagecustom status_code

from rest_framework.serializers import ValidationError
from rest_framework import status



class CustomAPIException(ValidationError):
    """
    raises API exceptions with custom messages and custom status codes
    """
    status_code = status.HTTP_400_BAD_REQUEST
    default_code = 'error'

    def __init__(self, detail, status_code=None):
        self.detail = detail
        if status_code is not None:
            self.status_code = status_code
Run Code Online (Sandbox Code Playgroud)


而在你的views,

from rest_framework import status

try:
    obj = self.get_object()
except:
    raise CustomAPIException("This object does not exist", status_code=status.HTTP_404_NOT_FOUND)
Run Code Online (Sandbox Code Playgroud)


响应将是这样的
{"detail": "This object does not exist"}

笔记

类的detail参数CustomAPIException采用str,listdict对象。如果您提供一个dict对象,那么它会将该 dict 作为异常响应返回

更新

正如@pratibha 所提到的,如果我们在序列化程序validate()validate_xxfieldName()方法中使用这个异常类,就不可能产生所需的输出。

为什么会有这种行为?
我在 SO 中写了一个类似的答案,这里Django REST Framework ValidationError 总是返回 400

如何在序列化程序的validate()方法中获得所需的输出?
继承CustomAPIExceptionrest_framework.exceptions.APIException而不是自rest_framework.serializers.ValidationError
即,

from rest_framework.exceptions import APIException


class CustomAPIException(APIException):
    # .... code
Run Code Online (Sandbox Code Playgroud)