gpt4 book ai didi

django - 在 Django REST Framework 中,为什么序列化程序可以正确处理模型中的字段级验证异常,但不能处理对象级验证?

转载 作者:行者123 更新时间:2023-12-02 03:25:24 25 4
gpt4 key购买 nike

为了说明我的问题,假设我有一个简单的 Person 模型,定义如下:

from django.db import models
from django.core.validators import MinLengthValidator, MaxLengthValidator, ValidationError

class Person(models.Model):
first_name = models.CharField(max_length=100, null=False, blank=False,
validators=[MinLengthValidator(limit_value=1),
MaxLengthValidator(limit_value=100)])
last_name = models.CharField(max_length=100, null=True, blank=True,
validators=[MinLengthValidator(limit_value=1),
MaxLengthValidator(limit_value=100)])

def clean(self):
self.validate()
super().clean()

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

def validate(self):
"""The first and last names cannot be the same strings."""
if (self.first_name and self.last_name and
self.first_name.lower() == self.last_name.lower()):
raise ValidationError('First and last names, if both are provided, cannot be the same.',
code='invalid',
params={'first_name': self.first_name,
'last_name': self.last_name})
  • 请注意,first_namelast_name 字段都具有与其关联的字段级验证。 (我的开发数据库是 SQLite,它不进行长度验证。因此我必须添加验证器。但这不是我的问题。)

我定义了两个简单的基于 APIView 的类:

from rest_framework import generics
from ..models import Person
from ..serializers import PersonSerializer

class PersonDetailView(generics.RetrieveUpdateDestroyAPIView):
name = 'person-detail'
queryset = Person.objects.all()
serializer_class = PersonSerializer
lookup_field = 'id'

class PersonListView(generics.ListCreateAPIView):
name = 'person-list'
queryset = Person.objects.all()
serializer_class = PersonSerializer
lookup_field = 'id'

我定义了一个基于 Django REST Framework 的 ModelSerializer 的序列化器:

from rest_framework import serializers
from ..models import Person

class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('id', 'first_name', 'last_name')

而且,我映射了一些 URL。

如果我 POST、PUT 或 PATCH 违反了字段级验证规则(例如,我尝试提交 101 个字符长的名字),Django REST Framework 会捕获模型类中的异常并正确显示它。以下是可浏览 API 中的内容:

enter image description here

但是,如果我 POST、PUT 或 PATCH 违反了对象级验证规则,Django REST 框架不会捕获异常,并且服务器崩溃并显示如下跟踪:

enter image description here

我的解决方案是将对象级验证添加到序列化器和模型中。这是带有自己的 validate 方法的序列化器:

from rest_framework import serializers
from rest_framework.validators import ValidationError

from ..models import Person

class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('id', 'first_name', 'last_name')

def validate(self, attrs):
first_name = attrs.get('first_name')
last_name = attrs.get('last_name')
if first_name and last_name and first_name.lower() == last_name.lower():
raise ValidationError('First and last names must be different.',
code='invalid')
return attrs

如果我这样做,那么 Django REST Framework 就会很好地处理异常:

enter image description here

这里(最后;-)是我的问题:

Why do I have to perform object-level validation in both the model and the serializer when I only have to do field-level validation in the model and the serializer will handle the exceptions just fine?

Is this how Django REST Framework is intended to behave? Seems like the serializer should be able to gracefully handle all ValidationErrors raised by the model.

最佳答案

DRF 3.0 后,.clean() 方法将不会作为序列化器验证的一部分被调用,就像使用 ModelForm 一样,请阅读此 https://www.django-rest-framework.org/community/3.0-announcement/#differences-between-modelserializer-validation-and-modelform .

关于django - 在 Django REST Framework 中,为什么序列化程序可以正确处理模型中的字段级验证异常,但不能处理对象级验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53568185/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com