Django Rest框架完整性错误捕获

yzxexxkh  于 2022-11-26  发布在  Go
关注(0)|答案(4)|浏览(170)

在Django Rest Framework中,我使用了序列化器、视图集和路由器的方法。每当我在Django Rest Framework的API视图中发布一个故意的错误时,它会抛出一个完整性错误。有没有办法尝试捕捉错误,比如如果数据中没有错误,就继续保存,但是如果有错误,会抛出一个JSON响应,其中包含一系列错误,比如:

[{'section':'This field can not be blank', 'first_name':'This field can not be blank', 'middle_name':'This field can not be blank', 'last_name':'This field can not be blank'}]

models.py

from django.db import models

# Create your models here.
# class AuditTable(models.Model):
#   date_created = models.DateTimeField(auto_now_add=True)
    # test_field = models.CharField(max_length=50, null=True, blank=True)

class Section(models.Model):
    name = models.CharField(max_length=50, default=None)

    def __str__(self):
        return self.name

class Student(models.Model):
    section = models.ForeignKey(Section, default=None)
    first_name = models.CharField(max_length=50, default=None)
    middle_name = models.CharField(max_length=50, default=None)
    last_name = models.CharField(max_length=50, default=None)

    def __str__(self):
        full_name = "%s %s %s" % (self.first_name, self.middle_name, self.last_name)
        return full_name

serializers.py

from rest_framework import serializers
from rest_framework.response import Response

from . models import *

class SectionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Section
        fields = ('name', )

class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = ('section', 'first_name', 'middle_name', 'last_name' )

viewsets.py

from rest_framework import viewsets

from . serializers import *
from . models import *

class SectionViewSet(viewsets.ModelViewSet):
    queryset = Section.objects.all()
    serializer_class = SectionSerializer

class StudentViewSet(viewsets.ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer

routers.py

from rest_framework import routers

from . viewsets import *

# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'students', StudentViewSet)
router.register(r'sections', SectionViewSet)

urls.py

from django.conf.urls import include, url

from . import views
from . routers import router

urlpatterns = [
    url(r'^$', views.index, name='testing_sample_index' ),
    url(r'^restful-form/$', views.web_service_form, name='testing_sample_web_service' ),

    url(r'^api/', include(router.urls)),
]
wmvff8tz

wmvff8tz1#

根据this answer,解决方案为:
viewsets.py

from django.db import IntegrityError    # Import IntegrityError
from rest_framework import viewsets
from rest_framework.exceptions import APIException  #Import APIException
from . serializers import *
from . models import *

class SectionViewSet(viewsets.ModelViewSet):
    queryset = Section.objects.all()
    serializer_class = SectionSerializer

    def create(self, request, *args, **kwargs):
        try:
            return super().create(request, *args, **kwargs)
        except IntegrityError as exc:
            raise APIException(detail=exc)
eyh26e7m

eyh26e7m2#

如果你有一个IntegrityError,那么你的模型就不是最新的数据库。
应设置唯一性约束以匹配数据库方案。
请注意,DRF可以使用UniqueValidator针对唯一约束进行验证

e0bqpujr

e0bqpujr3#

默认的CreateMixin实现在任何验证错误时都会引发异常。

class VerboseCreateModelMixin(object):
    """
    Create a model instance and return either created object or the validation errors.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

...然后在您的ViewSet中使用它:

class SectionViewSet(VerboseCreateModelMixin, viewsets.ModelViewSet):
    queryset = Section.objects.all()
    serializer_class = SectionSerializer
dm7nw8vv

dm7nw8vv4#

有一个更好的(在我看来)解决方案:Django Rest Framework有一个EXCEPTION_HANDLER,允许自定义处理默认情况下不处理的异常。
因此,您必须:
1.配置DRF以指定要使用的EXCEPTION_HANDLER。转到您的设置并添加以下内容:

REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'applications.utils.exception_handler'
    }

1.在指定的位置编写exception_handler函数逻辑(本例中为applications.utils,但您可以更改它):

def exception_handler(exc, context):
    """
    Handle Django ValidationError as an accepted exception by DRF.
    For the parameters, see ``exception_handler``
    """
    if isinstance(exc, IntegrityError):
        exc = DRFValidationError(detail=exc)
    return drf_exception_handler(exc, context)

现在,每当引发DRF的串行化程序未处理的IntegrityError时,此函数将其转换为DRFValidationError,DRFValidationError将得到正确处理,返回带有正确数据的400错误。

相关问题