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

2024-10-01 17:34:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我的模型中有refundablerefundable_price字段。我需要确保在refundableTrue的情况下refundable_price不是None

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

from django.core.exceptions import ValidationError

def save(self, **kwargs):
    self.full_clean()
    super().save(**kwargs)

def clean(self):
    super().clean()
    if self.refundable and self.refundable_price is None:
        raise ValidationError("V prípade refundovateľnej ponuky je nutné zadať sumu (je možné zadať aj 0)")

我使用ModelViewSet

class SubOfferViewSet(ModelViewSet):
    serializer_class = SubOfferSerializer
    filterset_fields = {
        # 'approved_by': ['exact'],
        # 'approved_dt': ['gte', 'lte', 'gt', 'lt'],
    }

    def get_queryset(self):
        return SubOffer.objects.all()

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

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

enter image description here

enter image description here 这是如何可能的,以及如何使其正常工作


Tags: selfcleannonesavedef错误pricekwargs
2条回答

仅通过默认的DRF句柄APIException(请参见source)。由于您正在上升Django'sValidationErrorinstead of DRF'sValidation`error,因此此处理程序返回None

要解决这个问题,您可以使用DRF中的ValidationError

from rest_framework.exceptions import ValidationError

还是自己写custom exception_handler更好:

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

处理所有验证错误(以及可能需要的任何其他错误)的干净方法是使用一个自定义的EXCEPTION_HANDLER来转换Django ValidationError到一个DRF

见:

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


def exception_handler(exc, context):

    if isinstance(exc, DjangoValidationError):
        exc = DRFValidationError(detail=exc.message_dict)

    return drf_exception_handler(exc, context)


"""
In settings:

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'path.to_module.drf.exception_handler',
}

"""

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

一个更深入的例子:https://github.com/HackSoftware/Styleguide-Example/blob/master/styleguide_example/api/mixins.py

相关问题 更多 >

    热门问题