Django Rest Framework 自动处理哪些类型的验证?
What types of validations are automatically handled by Django Rest Framework?
假设我有一个定义如下的模型:
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator
alphanumeric_validator = RegexValidator(r'^[a-zA-Z0-9]*$', 'Only alphanumeric characters are allowed.')
class Person(model.Model):
name = models.CharField(max_length=60, validators=[alphanumeric_validator])
number = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100)])
email = models.EmailField()
现在,假设我正在使用 Django Rest Framework 序列化和创建 Person 对象。它看起来像这样:
from rest_framework import serializers
from .models import Person
from rest_framework.response import Response
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('name', 'number', 'email')
class PostPerson(APIView):
def post(self, request, format=None):
serializer = PersonSerializer(data=request.data)
if serializer.is_valid():
serializer.save()=
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
现在,我的问题是:当我使用 is_valid()
验证序列化器时,DRF 是否处理 validators=[alphanumeric_validator]
和 validators=[MinValueValidator(0), MaxValueValidator(100)]
?此外,我确信 DRF 会自动处理 max_length
属性,但它是否还会使用正确的正则表达式检查 email
是否为实际电子邮件地址?
我通常只是对 clean、full_clean 以及在表单验证和序列化程序验证期间调用的所有方法感到困惑,因此希望得到一些可靠的解释。
提前致谢。
Django rest 框架验证的行为类似于 Django ModelForm
验证;它从您的模型字段中获取参数并进行相应验证。
例如,我们将采用一个简单的模型和序列化程序 class,它的字段具有唯一性约束。
class CustomerReportRecord(models.Model):
time_raised = models.DateTimeField(default=timezone.now, editable=False)
reference = models.CharField(unique=True, max_length=20)
class CustomerReportSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerReportRecord
当我们打开 Django shell 时,我们可以看到验证器已应用于序列化程序(注意 max_length
和 validators
列表)
>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
>>> print(repr(serializer))
CustomerReportSerializer():
id = IntegerField(label='ID', read_only=True)
time_raised = DateTimeField(read_only=True)
reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])
打印序列化程序实例的 repr
将准确显示它应用的验证规则。没有在模型实例上调用额外的隐藏验证行为。
当谈到 .clean
和 .full_clean
方法时,这只是验证用户输入数据的另一种方法——将其规范化为一致的格式。当您在 表单 上调用 .is_valid()
方法时,这些以 Django 形式执行,而不是在您的休息框架序列化程序中执行。
回到 REST 框架验证器。让我们看一下 Serializer.to_internal_value
方法。
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, dict):
message = self.error_messages['invalid'].format(
datatype=type(data).__name__
)
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
})
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
if validate_method is not None:
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = list(exc.messages)
except SkipField:
pass
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
我们可以在这里看到序列化程序调用 field.run_validation
方法,该方法使用模型字段验证器,如果验证失败,它们会引发 DjangoValidationError
。如果成功,它将继续 运行 存在的任何其他验证器,例如序列化程序字段特定的验证器 (.validate_<field_name>
)。
在此处详细了解验证及其在 Django 和 DRF 中的工作原理:
- Form Field Validation Django 2.1
- Validators - DRF Docs
- Serializer Validation - DRF Docs
- Correct way to validate Django Models
- DRF Serializer code
希望这有助于理解验证在 DRF 中的工作方式,哪怕只是一点点
编辑:只要您存储电子邮件的字段在模型中定义为 EmailField
,DRF 就会验证电子邮件。有关更多信息,请参见 here
假设我有一个定义如下的模型:
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator
alphanumeric_validator = RegexValidator(r'^[a-zA-Z0-9]*$', 'Only alphanumeric characters are allowed.')
class Person(model.Model):
name = models.CharField(max_length=60, validators=[alphanumeric_validator])
number = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100)])
email = models.EmailField()
现在,假设我正在使用 Django Rest Framework 序列化和创建 Person 对象。它看起来像这样:
from rest_framework import serializers
from .models import Person
from rest_framework.response import Response
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('name', 'number', 'email')
class PostPerson(APIView):
def post(self, request, format=None):
serializer = PersonSerializer(data=request.data)
if serializer.is_valid():
serializer.save()=
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
现在,我的问题是:当我使用 is_valid()
验证序列化器时,DRF 是否处理 validators=[alphanumeric_validator]
和 validators=[MinValueValidator(0), MaxValueValidator(100)]
?此外,我确信 DRF 会自动处理 max_length
属性,但它是否还会使用正确的正则表达式检查 email
是否为实际电子邮件地址?
我通常只是对 clean、full_clean 以及在表单验证和序列化程序验证期间调用的所有方法感到困惑,因此希望得到一些可靠的解释。
提前致谢。
Django rest 框架验证的行为类似于 Django ModelForm
验证;它从您的模型字段中获取参数并进行相应验证。
例如,我们将采用一个简单的模型和序列化程序 class,它的字段具有唯一性约束。
class CustomerReportRecord(models.Model):
time_raised = models.DateTimeField(default=timezone.now, editable=False)
reference = models.CharField(unique=True, max_length=20)
class CustomerReportSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerReportRecord
当我们打开 Django shell 时,我们可以看到验证器已应用于序列化程序(注意 max_length
和 validators
列表)
>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
>>> print(repr(serializer))
CustomerReportSerializer():
id = IntegerField(label='ID', read_only=True)
time_raised = DateTimeField(read_only=True)
reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])
打印序列化程序实例的 repr
将准确显示它应用的验证规则。没有在模型实例上调用额外的隐藏验证行为。
当谈到 .clean
和 .full_clean
方法时,这只是验证用户输入数据的另一种方法——将其规范化为一致的格式。当您在 表单 上调用 .is_valid()
方法时,这些以 Django 形式执行,而不是在您的休息框架序列化程序中执行。
回到 REST 框架验证器。让我们看一下 Serializer.to_internal_value
方法。
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, dict):
message = self.error_messages['invalid'].format(
datatype=type(data).__name__
)
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
})
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
if validate_method is not None:
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = list(exc.messages)
except SkipField:
pass
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
我们可以在这里看到序列化程序调用 field.run_validation
方法,该方法使用模型字段验证器,如果验证失败,它们会引发 DjangoValidationError
。如果成功,它将继续 运行 存在的任何其他验证器,例如序列化程序字段特定的验证器 (.validate_<field_name>
)。
在此处详细了解验证及其在 Django 和 DRF 中的工作原理:
- Form Field Validation Django 2.1
- Validators - DRF Docs
- Serializer Validation - DRF Docs
- Correct way to validate Django Models
- DRF Serializer code
希望这有助于理解验证在 DRF 中的工作方式,哪怕只是一点点
编辑:只要您存储电子邮件的字段在模型中定义为 EmailField
,DRF 就会验证电子邮件。有关更多信息,请参见 here