zoukankan      html  css  js  c++  java
  • DRF框架之Serializer序列化器的反序列化操作

    昨天,我们完成了Serializer序列化器的反序列化操作,那么今天我们就来学习Serializer序列化器的最后一点知识,反序列化操作。

    首先,我们定要明确什么是反序列化操作?

    反序列化操作:JOSN数据 --> 字典数据 -->验证通过的字典数据 --> 模型数据

    我们在进行反序列化操作时,首先要保证就是拿到的字典数据一定要通过认证。

    反序列化操作的步骤:

    1. 定义一个序列化器(这里我们采用昨天定义好的序列化器即可)。

    class BookInfoSerializer(serializers.Serializer):
        '''定义图书序Serializer序列化器'''
        # 这里的字段需要和模型类中的字段名、字段类型、约束一致
        id = serializers.IntegerField(label='ID', read_only=True)
        btitle = serializers.CharField(label='名称', max_length=20)
        bpub_date = serializers.DateField(label='发布日期', required=False)
        bread = serializers.IntegerField(label='阅读量', required=False)
        bcomment = serializers.IntegerField(label='评论量', required=False)

    2. 准备JSON数据或字典数据

    data = {'btitle':'大话西游','bpub_date':'2020-02-06'}

    3. 验证字典数据

    我们使用序列化器对象点出is_valid()方法进行验证,验证成功返回True,否则返回False。

    3.1 验证通过

    当字典数据通过校验时,我们可以通过序列化器对象点出validated_data属性获取到校验成功后的字典数据

    >>> data = {'btitle':'大话西游','bpub_date':'2020-02-06'}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    True
    >>> s.validated_data
    OrderedDict([('btitle', '大话西游'), ('bpub_date', datetime.date(2020, 2, 6))])

    3.2 验证未通过

    当字典数据未通过校验时,我们可以通过序列化器对象点出errors属性获取到错误信息

    >>> data = {'bpub_date': 123}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    False
    >>> s.validated_data
    {}
    >>> s.errors
    {'btitle': [ErrorDetail(string='This field is required.', code='required')], 'bpub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY-MM-DD.', code='invalid')]}

    3.3 对单一字段进行验证

    我们需要在序列化器类中定义一个名字为(validate_字段名)的方法,来补充验证逻辑。

    def validate_btitle(self, value):
        '''
        对btitle字段进行验补充
        :param value: 前段传递的btitle数据
        :return: 验证成功:返回value;验证失败:返回错误信息
        '''   

    当验证失败时,我们使用raise抛出异常的方式来返回错误信息。

    例如:

        # 补充单一字段的验证逻辑
        def validate_btitle(self, value):
            '''
            对btitle字段进行验补充
            :param value: 前段传递的btitle数据
            :return: 验证成功:返回value;验证失败:返回错误信息
            '''
    
            # 验证逻辑
            if 'django' not in value:
                # 失败
                raise serializers.ValidationError('btitle数据错误信息')
    
            # 成功
            return value

    Shell测试代码:

    >>> from booktest.serializers import BookInfoSerializer
    >>> data = {'btitle': 'python'}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    False
    >>> s.errors
    {'btitle': [ErrorDetail(string='btitle数据错误信息', code='invalid')]}
    >>> data = {'btitle': 'python_django'}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    True
    >>> s.validated_data
    OrderedDict([('btitle', 'python_django')])

    3.4 对所有字段进行扩展验证

    我们需要在序列化器中定义一个名字为(validate())的方法,来补充对所有字段进行扩展验证的逻辑。

    def validate(self, attrs):
            '''
            对多个字段进行验证
            :param attrs: 前段传递的字典数据
            :return: 验证成功:返回attrs;验证失败:返回错误信息
            '''

    同样,我们也需要使用raise抛出异常信息。

    例如:

    def validate(self, attrs):
            '''
            对多个字段进行验证
            :param attrs: 前段传递的字典数据
            :return: 验证成功:返回attrs;验证失败:返回错误信息
            '''
    
            # 验证逻辑:这里需要验证的是bread大于bcomment
            bread = attrs.get('bread')
            bcomment = attrs.get('bcomment')
    
            if bread < bcomment:
                # 失败
                raise serializers.ValidationError('bread需要大于bcomment')
    
            # 成功
            return attrs

    Shell测试代码:

    >>> from booktest.serializers import BookInfoSerializer
    >>> data = {'btitle': 'about django', 'bread': 10, 'bcomment': 20}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    False
    >>> s.errors
    {'non_field_errors': [ErrorDetail(string='bread需要大于bcomment', code='invalid')]}
    >>> data = {'btitle': 'about django', 'bread': 50, 'bcomment': 20}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    True
    >>> s.validated_data
    OrderedDict([('btitle', 'about django'), ('bread', 50), ('bcomment', 20)])

    4. 验证后的字典数据 ---> 模型数据

    这里,我们已将到了数据反序列化的最后一步操作了。

    同样,我们也应该知道,将验证后的字典数据转模型数据的实质,其实就是将验证过的字典数据添加到数据库中。

    那么,对于将数据保存到数据库中的操作一共就两种:一种是添加数据的操作,一种是修改数据的操作。

    4.1 添加数据

    我们,想要添加数据,就需要在序列化器类中定义一个create()方法。

    def create(self, validated_data):
            '''
            序列化器进行新增数据的方法
            :param validated_data: 通过验证的字典数据
            :return:根据RESTful设计方式,需要将添加的数据返回
            '''
            
            return ORM添加数据的语句(模型类.objects.create(**validated_data))

    例如:

    def create(self, validated_data):
            '''
            序列化器进行新增数据的方法
            :param validated_data: 通过验证的字典数据
            :return:根据RESTful设计方式,需要将添加的数据返回
            '''
    
            return BookInfo.objects.create(**validated_data)

    在这里,我们需要返回添加的数据给前端,因为我们定义的API是遵守RESTful设计风格的。

    Shell测试代码:

    >>> from booktest.serializers import BookInfoSerializer
    >>> data = {'btitle': 'django手册', 'bpub_date': '2020-02-05', 'bread': 20, 'bcomment': 10}
    >>> s = BookInfoSerializer(data=data)
    >>> s.is_valid()
    True
    >>> s.save()
    <BookInfo: django手册>

    注意:

    当我们创建序列化对象时,只传递data数据,就表示我们需要向数据库里添加数据

    所以,当序列化器对象调用save()方法时,会自动调用序列化器类中的create()方法

    4.2 修改数据

    我们,想要修改数据时,需要在序列化器类中定义一个update()方法。

        def update(self, instance, validated_data):
            '''
            序列化器进行修改数据的方法
            :param instance: 需要修改的模型对象
            :param validated_data: 前端传递的字典数据
            :return: 根据RESTful设计方式,需要将修改的数据返回
            '''
            
            # 新值覆盖旧值
            instance.字段名 = validated_data.get(字段名)
            instance.save()
            return instance

    例如:

    def update(self, instance, validated_data):
            '''
            序列化器进行修改数据的方法
            :param instance: 需要修改的模型对象
            :param validated_data: 前端传递的字典数据
            :return: 根据RESTful设计方式,需要将修改的数据返回
            '''
    
            # 新值覆盖旧值
            instance.btitle = validated_data.get('btitle')
            instance.bpub_date = validated_data.get('bpub_date')
            instance.bread = validated_data.get('bread')
            instance.bcomment = validated_data.get('bcomment')
            instance.save()
    
            return instance

    我们同样也需要将修改的数据返回给前端。

    Shell测试代码:

    from booktest.models import BookInfo
    from booktest.serializers import BookInfoSerializer
    >>> book = BookInfo.objects.get(id=10)
    >>> data = {'btitle': 'python_django手册', 'bpub_date': '2020-02-05', 'bread': 20, 'bcomment': 10}
    >>> s = BookInfoSerializer(instance=book,data=data)
    >>> s.is_valid()
    True
    >>> s.save()
    <BookInfo: python_django手册>

    注意:

    当我们创建序列化器对象时,传递了instancedata数据,就表示我们需要进行数据的修改操作。

    所以,当我们使用序列化器对象调用save()方法时,会自动调用序列化器类中的update()方法。

    至此,我们的Serializer序列化的反序列化操作就学习完毕了。

    序列化器的学习中,几乎没有什么逻辑点,因为,使用的是他人已经封装好的框架,所以必须遵守框架的规定来开发,只需要,记住模版即可。

    该花的钱要花,该吃的饭要吃。
  • 相关阅读:
    Linux内核(5)
    Linux内核(4)
    Linux内核(3)
    Linux内核(2)
    Linux内核(1)
    Linux时间子系统(十七) ARM generic timer驱动代码分析
    Linux时间子系统(十六) clockevent
    Linux时间子系统(十五) clocksource
    Linux时间子系统(十四) tick broadcast framework
    Linux时间子系统(十三) Tick Device layer综述
  • 原文地址:https://www.cnblogs.com/chao666/p/12269977.html
Copyright © 2011-2022 走看看