DRF 验证 - 当 Model.clean 中出现错误时返回错误 500

Mil*_*ano 2 python django django-rest-framework

我的模型中有字段refundable和。refundable_price我需要确定没有refundable_priceNone以防refundable万一True

\n\n

因为我想要它无处不在,所以我重写了SubOffer.clean方法:

\n\n
from django.core.exceptions import ValidationError\n\ndef save(self, **kwargs):\n    self.full_clean()\n    super().save(**kwargs)\n\ndef clean(self):\n    super().clean()\n    if self.refundable and self.refundable_price is None:\n        raise ValidationError("V pr\xc3\xadpade refundovate\xc4\xbenej ponuky je nutn\xc3\xa9 zada\xc5\xa5 sumu (je mo\xc5\xben\xc3\xa9 zada\xc5\xa5 aj 0)")\n
Run Code Online (Sandbox Code Playgroud)\n\n

而我用的是ModelViewSet.

\n\n
class SubOfferViewSet(ModelViewSet):\n    serializer_class = SubOfferSerializer\n    filterset_fields = {\n        # \'approved_by\': [\'exact\'],\n        # \'approved_dt\': [\'gte\', \'lte\', \'gt\', \'lt\'],\n    }\n\n    def get_queryset(self):\n        return SubOffer.objects.all()\n
Run Code Online (Sandbox Code Playgroud)\n\n

奇怪的是,当我发送POST到时,如果 中存在错误,ViewSet它会返回500而不是JSON错误Suboffer.clean。其他错误工作正常。

\n\n

AJAX我用的时候和用的时候是一样的DRF API Viewer

\n\n

在此输入图像描述

\n\n

在此输入图像描述\n这怎么可能以及如何使其正常工作?

\n

Pau*_*eri 12

处理所有验证错误(以及您可能想要的任何其他错误)的一种简洁方法是使用一个EXCEPTION_HANDLER将 Django 转换 ValidationError为 DRF 的自定义方法。

看:

from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework.exceptions import ValidationError as DRFValidationError
from rest_framework.serializers import as_serializer_error
from rest_framework.views import exception_handler as drf_exception_handler


def exception_handler(exc, context):

    if isinstance(exc, DjangoValidationError):
        exc = DRFValidationError(as_serializer_error(exc))

    return drf_exception_handler(exc, context)


"""
In settings:

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'path.to_module.drf.exception_handler',
}
"""
Run Code Online (Sandbox Code Playgroud)

来源:https ://gist.github.com/twidi/9d55486c36b6a51bdcb05ce3a763e79f

更深入的示例:https://github.com/HackSoftware/Django-Styleguide-Example/blob/9761c7592af553084e95bb5f8f9407a173aac66f/styleguide_example/api/exception_handlers.py

  • 救星!特别是 as_serializer_error。让您的 API 按照您期望的方式响应。 (3认同)

nev*_*ner 5

默认情况下仅使用 DRF 句柄APIException(请参阅源代码)。由于您出现了Django'sValidationError instead of DRF'sValidation` 错误,因此该处理程序返回 None。

因此,要解决此问题,您可以使用ValidationErrorDRF:

from rest_framework.exceptions import ValidationError
Run Code Online (Sandbox Code Playgroud)

或者编写您自己的自定义异常处理程序更好::

from rest_framework.views import exception_handler
from django.core.exceptions import ValidationError

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 response is None and isinstance(exc, ValidationError):
        return Response(status=400)

    return response
Run Code Online (Sandbox Code Playgroud)