Django Rest Framework 自动处理哪些类型的验证?

dar*_*rse 1 django django-serializer 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()
Run Code Online (Sandbox Code Playgroud)

现在,假设我正在使用 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)
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是:当我使用 验证序列化器时is_valid(),DRF 是否处理validators=[alphanumeric_validator], 和validators=[MinValueValidator(0), MaxValueValidator(100)]?另外,我确信 DRF 会自动处理该max_length属性,但它是否也会email使用正确的正则表达式检查是否是实际的电子邮件地址?

我通常只是对 clean、full_clean 以及表单验证和序列化器验证期间调用的所有方法感到困惑,因此希望获得一些可靠的解释。

提前致谢。

Kri*_*ski 5

Django Rest 框架验证的行为与 Django 验证类似ModelForm;它从模型字段中获取参数并进行相应的验证。

\n\n

例如,我们将采用一个简单的模型和序列化器类,该类具有一个具有唯一性约束的字段。

\n\n
class CustomerReportRecord(models.Model):\n    time_raised = models.DateTimeField(default=timezone.now, editable=False)\n    reference = models.CharField(unique=True, max_length=20)\n\n\nclass CustomerReportSerializer(serializers.ModelSerializer):\n    class Meta:\n        model = CustomerReportRecord\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我们打开 Django shell 时,我们可以看到验证器已应用于序列化器(注意max_lengthvalidators列表)

\n\n
>>> from project.example.serializers import CustomerReportSerializer\n>>> serializer = CustomerReportSerializer()\n>>> print(repr(serializer))\nCustomerReportSerializer():\n    id = IntegerField(label=\'ID\', read_only=True)\n    time_raised = DateTimeField(read_only=True)\n    reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])\n
Run Code Online (Sandbox Code Playgroud)\n\n

打印repr序列化器实例的 会准确地显示它应用的验证规则。模型实例上没有调用额外的隐藏验证行为。

\n\n

当涉及.clean.full_clean方法时,只是验证用户输入数据 \xe2\x80\x94 的另一种方法,将其标准化为一致的格式。当您在表单.is_valid()上调用方法时,这些将在 Django 表单中执行,而不是在其余框架序列化器中执行。

\n\n

回到 REST 框架验证器。我们来看看Serializer.to_internal_value方法。

\n\n
def to_internal_value(self, data):\n    """\n    Dict of native values <- Dict of primitive datatypes.\n    """\n    if not isinstance(data, dict):\n        message = self.error_messages[\'invalid\'].format(\n            datatype=type(data).__name__\n        )\n        raise ValidationError({\n            api_settings.NON_FIELD_ERRORS_KEY: [message]\n        })\n\n    ret = OrderedDict()\n    errors = OrderedDict()\n    fields = self._writable_fields\n\n    for field in fields:\n        validate_method = getattr(self, \'validate_\' + field.field_name, None)\n        primitive_value = field.get_value(data)\n        try:\n            validated_value = field.run_validation(primitive_value)\n            if validate_method is not None:\n                validated_value = validate_method(validated_value)\n        except ValidationError as exc:\n            errors[field.field_name] = exc.detail\n        except DjangoValidationError as exc:\n            errors[field.field_name] = list(exc.messages)\n        except SkipField:\n            pass\n        else:\n            set_value(ret, field.source_attrs, validated_value)\n\n    if errors:\n        raise ValidationError(errors)\n\n    return ret\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们可以在这里看到序列化器调用field.run_validation方法,该方法使用模型字段验证器,并且DjangoValidationError如果验证失败,它们会引发一个错误。如果成功,它将继续运行现有的任何其他验证器,例如序列化器字段特定验证器 ( .validate_<field_name>)。

\n\n

在此处阅读有关验证及其在 Django 和 DRF 中如何工作的更多信息:

\n\n
    \n
  1. 表单字段验证 Django 2.1
  2. \n
  3. 验证器 - DRF 文档
  4. \n
  5. 序列化器验证 - DRF 文档
  6. \n
  7. 验证 Django 模型的正确方法
  8. \n
  9. DRF 序列化器代码
  10. \n
\n\n

希望这有助于理解 DRF 中验证的工作原理,哪怕只是一点点

\n\n

编辑:只要您存储电子邮件的字段被定义为EmailField模型中的 an ,那么 DRF 就会验证电子邮件。更多相关内容可以在这里找到

\n