Django rest_framework自定义错误信息

6

我有一个API端点,它将使用rest_framework的serializer.is_valid()进行输入验证,如果出错,则返回自定义错误消息和响应。

serializer = FormSerializer(data=data)
if not serializer.is_valid(raise_exception=False):
    return Response({"Failure": "Error"}, status=status.HTTP_400_BAD_REQUEST)

不使用raise_exception=True提供的通用响应,是否有可能填写验证错误?我试图避免使用通用响应,因为如果有多个错误,它将显示所有验证错误。

响应将类似于:

return Response(
     {
          "Failure": "Error", 
          "Error_list": {"field1": "This field is required"}
     },
     status=status.HTTP_400_BAD_REQUEST
) 
3个回答

13

创建一个自定义异常类,如下:

from rest_framework.exceptions import PermissionDenied
from rest_framework import status


class MyCustomExcpetion(PermissionDenied):
    status_code = status.HTTP_400_BAD_REQUEST
    default_detail = "Custom Exception Message"
    default_code = 'invalid'

    def __init__(self, detail, status_code=None):
        self.detail = detail
        if status_code is not None:
            self.status_code = status_code


为什么我继承了PermissionDenied异常类?
参见此Stack Overflow帖子--为什么DRF的ValidationError总是返回400

然后在您的序列化器中,将异常提升为:

class SampleSerializer(serializers.ModelSerializer):
    class Meta:
        fields = '__all__'
        model = SampleModel

    def validate_age(self, age):  # field level validation
        if age > 10:
            raise MyCustomExcpetion(detail={"Failure": "error"}, status_code=status.HTTP_400_BAD_REQUEST)
        return age

    def validate(self, attrs): # object level validation
        if some_condition:
            raise MyCustomExcpetion(detail={"your": "exception", "some_other": "key"}, status_code=status.HTTP_410_GONE)
        return attrs
agenameSampleModel类的两个字段。


响应将会是这样的:

enter image description here
使用此方法,
1. 您可以自定义JSON响应
2. 您可以返回任何状态代码
3. 您不需要在 serializer.is_valid() 方法中传递 True(这是不推荐的)。


在对象级别验证中,是否可以捕获字段验证错误? 我有超过20个字段,希望只捕获对象级别验证中的第一个字段验证错误。 - Clueless_Coder
根据我的示例,您可以通过attrs['your_field']获取字段的值。然后自行检查特定的验证。如果验证失败,请引发CustomException异常。 - JPG
如果我使用name = serializers.CharField(max_length=10)作为字段验证,并在对象级别验证中捕获它,这是不可能的吗? - Clueless_Coder
在这种情况下,只有在**is_valid(True)(即设置了raise_exception=True)时,它才会引发一个HTTP 400 Bad Request**。 - JPG
@Clueless_Coder 有什么问题吗? - JPG

2

你可以编写自定义的错误处理程序

from rest_framework.views import exception_handler

def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)
    if response is not None:
        response.data['Failure'] = 'Error'

    return response

@JerinPeterGeorge 是的。它只是在响应中添加了"Failure": "Error", - neverwalkaloner

2
一个简单的方法是使用其中一个异常消息,例如NotFound。请参见文档中的NotFound。最初的回答。
# views.py
from rest_framework.exceptions import NotFound

class myview(viewsets.ModelViewSet):
    def perform_create(self, serializer):
        raise NotFound("My text here")

那会返回一个404错误,并将响应更改为你的文本。最初的回答中已经有这个内容。
HTTP 404 Not Found
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
    "detail": "my text here"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接