django rest框架中的数据和验证数据之间有什么区别?

use*_*105 3 django django-rest-framework

django休息框架在验证后对数据进行了哪些转换?是否只在可能的情况下将字符串解析为int?

Emm*_*ali 7

反序列化

数据是串行器的输入,例如

serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})

如您所见,电子邮件无效,因此适用以下规则(来自官方文件)

在反序列化数据时,您始终需要在尝试访问经过验证的数据之前调用is_valid(),或者保存对象实例

serializer.is_valid()
Run Code Online (Sandbox Code Playgroud)

如果data您尝试反序列化有效,#True则可以访问经过验证的数据

serializer.validated_data
Run Code Online (Sandbox Code Playgroud)

加成

验证后没有数据转换,它只检查您的数据是否有效,如果发生任何验证错误,该.errors属性将包含表示结果错误消息的字典.

一个很好的例子就是你进行现场验证

class CommentSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)

    def validate_title(self, value):
        if 'django' not in value.lower():
           raise serializers.ValidationError("Title is not about Django")
        return value
Run Code Online (Sandbox Code Playgroud)

validate_title每次调用时都会调用.is_valid(),因为你可以看到它只检查标题是否与django相关,如果为True,则返回此标题中返回的值,否则引发ValidationError.这里的数据没有变化

  • 这并不能回答问题。数据看起来总是与经过验证的数据相同吗? (3认同)

小智 7

您可以在CommentSerializer.validate_content方法中自定义数据:

这是你的序列化器:

class CommentSerializer(serializers.Serializer):
    email=serializers.EmailField()
    content=serializers.CharField()
    def validate_content(self,value):
        #If content is 'baz' returns 'foo'
        if value and value == "baz":
            return "foo"
        return value
Run Code Online (Sandbox Code Playgroud)

所以:让我们尝试错误的价值观(电子邮件)

>>> serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})

>>> serializer.data
Traceback (most recent call last):
    raise AssertionError(msg)
AssertionError: When a serializer is passed a `data` keyword argument you must call `.is_valid()` before attempting to access the serialized `.data` representation.
You should either call `.is_valid()` first, or access `.initial_data` instead.

>>> serializer.initial_data
{'content': 'baz', 'email': 'foobar'}

>>> serializer.validated_data
Traceback (most recent call last):
   raise AssertionError(msg) 
AssertionError: You must call `.is_valid()` before accessing `.validated_data`.

>>> serializer.is_valid()
False

>>> serializer.data
{'content': 'baz', 'email': 'foobar'}

>>> serializer.validated_data
{}

>>> serializer.errors
{'email': [u'Enter a valid email address.']}
Run Code Online (Sandbox Code Playgroud)

现在让我们试试正确的值

>>> serializer2 = CommentSerializer(data={'email': 'foobar@email.it', 'content': 'baz'})  
>>> serializer2.is_valid()
True

>>> serializer2.initial_data
{'content': 'baz', 'email': 'foobar@email.it'}
>>> serializer2.errors
{}

>>> serializer2.data
{'content': u'foo', 'email': u'foobar@email.it'}

>>> serializer2.validated_data
OrderedDict([(u'email', u'foobar@email.it'), (u'content', u'foo')])
Run Code Online (Sandbox Code Playgroud)

所以:

  • data:是一个dict,只有在is_valid()之后才能看到它(你只能看到未经验证的值)
  • validated_data是一个OrderedDict,只有在is_valid() && is_valid()== True后才能看到它


ber*_*cho 6

data并且validated_data 不会总是相同的。例如:

class UserSerializer(serializers.Serializer):
    name = serializers.CharField()
    phone = serializers.CharField(required=False, allow_null=True)
Run Code Online (Sandbox Code Playgroud)

我们可以得到不同的数据:

>>> user = UserSerializer(data={'name': 'Foo'})
>>> user.is_valid()
True
>>> user.data
{'name': 'Foo', 'phone': None}
>>> user.validated_data
{'name': 'Foo'}
Run Code Online (Sandbox Code Playgroud)

根据BaseSerializer内部代码data属性只是self.to_representation(self.validated_data)在序列化程序被验证时:

elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
    self._data = self.to_representation(self.validated_data)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,to_representation内部代码设置为None这些情况。


由于这种行为,我建议使用validated_dataover data。如果您使用这样data的序列化程序,并基于 显式设置对象的属性,则data可以设置为None初始数据中不存在的属性。