zoukankan      html  css  js  c++  java
  • 【1120 | Day63】序列化对象和反序列化对象

    一、创建序列器对象

    定义好Serializer类后,就可以创建Serializer对象了,具体构造方法为:

    Serializer(instance=None, data=empty, **kwarg)
    

    参数:

    instance: 用于序列化时,将模型类对象传入instance参数 。

    data: 用于反序列化时,将要被反序列化的数据传入data参数 。

    context: 除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据。

    serializer = AccountSerializer(account, context={'request': request})
    
    //通过context参数附加的数据,可以通过Serializer对象的context属性获取。
    

    注意:

    1. 序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。
    2. 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时,将使用数据传入。
    3. drf提供的视图会帮我们将dict转换成json,或者将客户端传来的数据转为dict

    二、序列化对象

    序列化器的使用分两个阶段:

    1. 客户端请求时,使用序列化器可以完成对数据的反序列化(write)
    2. 服务器响应时,使用序列化器可以完成对数据的序列化(read)

    第一步:查找对象或对象集

    //对象
    from booktest.models import BookInfo
    
    book = BookInfo.objects.get(id=2)
    
    //对象集
    from booktest.models import BookInfo
    
    book_qs = BookInfo.objects.all()
    

    第二步:构造序列化器对象

    //对象
    from booktest.serializers import BookInfoSerializer
    
    serializer = BookInfoSerializer(book)
    
    //对象集
    from booktest.serializers import BookInfoSerializer
    
    //如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补
    充说明
    serializer = BookInfoSerializer(book_qs, many=True)
    

    第三步:获取序列化数据

    //对象
    serializer.data
    
    # {'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40,
    'image': None}
    
    //对象集
    serializer.data
    
    # [OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread',
    36), ('bcomment', 40), ('image', N]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'),
    ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]),
    OrderedDict([('id', 4), ('btitle', '雪山飞狐'), ('bpub_date', '1987-11-11'), ('bread',
    58), ('bcomment', 24), ('ima None)]), OrderedDict([('id', 5), ('btitle', '西游记'),
    ('bpub_date', '1988-01-01'), ('bread', 10), ('bcomment', 10), ('im',
    'booktest/xiyouji.png')])]
    

    三、反序列化对象

    流程概述

    反序列化是相似的。

    • 验证:is_valid()

    该方法带有一个可选raise_exception标志,serializers.ValidationError如果存在验证错误,它将导致引发异常。这些异常由REST框架提供的默认异常处理程序自动处理,并且将HTTP 400 Bad Request默认返回响应。

    • True

      • validated_data
    • False

      • 字段错误>>>errors
      • 非字段错误>>>NON_FIELD_ERRORS_KEY
    • 保存

      • create( )
      • update( )

    具体操作

    1. 验证

    如我们前面定义过的BookInfoSerializer

    class BookInfoSerializer(serializers.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)
         image = serializers.ImageField(label='图片', required=False)
    

    通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证

    from booktest.serializers import BookInfoSerializer
    
    data = {'bpub_date': 123}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid() # 返回False
    serializer.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')]}
    
    serializer.validated_data # {}
    data = {'btitle': 'python'}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid() # True
    serializer.errors # {}
    serializer.validated_data # OrderedDict([('btitle', 'python')])
    

    is_valid()方法还可以在验证失败时抛出异常,通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应

    # Return a 400 response if the data was invalid.
    
    serializer.is_valid(raise_exception=True)
    

    2. 保存

    前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以将数据转成模型类对象

    class BookInfoSerializer(serializers.Serializer):
     """图书数据序列化器"""
         ...
         def create(self, validated_data):
         	"""新建"""
         	return BookInfo(**validated_data)
         def update(self, instance, validated_data):
         	"""更新,instance为要更新的对象实例"""
             instance.btitle = validated_data.get('btitle', instance.btitle)
             instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
             instance.bread = validated_data.get('bread', instance.bread)
             instance.bcomment = validated_data.get('bcomment', instance.bcomment)
             return instance
    

    如果需要在返回数据对象的时候,也将数据保存到数据库中,则可以进行如下修改

    class BookInfoSerializer(serializers.Serializer):
     """图书数据序列化器"""
         ...
         def create(self, validated_data):
             """新建"""
             return BookInfo.objects.create(**validated_data)
         def update(self, instance, validated_data):
             """更新,instance为要更新的对象实例"""
             instance.btitle = validated_data.get('btitle', instance.btitle)
             instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
             instance.bread = validated_data.get('bread', instance.bread)
             instance.bcomment = validated_data.get('bcomment', instance.bcomment)
             instance.save()
             return instance
    

    通过save()方法返回一个数据对象实例

    book = serializer.save()
    

    3. 补充

    如果创建序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create() 被调用

    from db.serializers import BookInfoSerializer
    
    data = {'btitle': '封神演义'}
    serializer = BookInfoSerializer(data=data)  #没有传入instance实例
    serializer.is_valid() # True
    serializer.save() # <BookInfo: 封神演义>
    

    相反,如果传递了instance实例,则调用save()方法的时候,update()被调用

    from db.models import BookInfo
    
    book = BookInfo.objects.get(id=2)
    data = {'btitle': '倚天剑'}
    serializer = BookInfoSerializer(book, data=data) #传入instance实例book
    serializer.is_valid() # True
    serializer.save() # <BookInfo: 倚天剑>
    book.btitle # '倚天剑'
    

    在对序列化器进行save()保存时,可以额外传递数据,这些数据可以在create()和update() 中的validated_data参数获取到

    # request.user 是django中记录当前登录用户的模型对象
    
    serializer.save(owner=request.user)
    

    默认序列化器必须传递所有required的字段,否则会抛出验证异常。但是我们可以使用 partial参数来允许部分字段更新

    # Update `book` with partial data
    
    serializer = BookInfoSerializer(book, data={'title': u'Python'}, partial=True)
    

    还是不清楚的可以参考这两篇,个人认为写得很详细:

  • 相关阅读:
    case 条件语句
    shell 函数
    if条件语句
    IP地址分类和分段
    shell脚本的条件测试与比较
    bc命令
    [LeetCode]Remove Duplicates from Sorted Array II
    [LeetCode]Merge Two Sorted Lists
    [LeetCode]Climbing Stairs
    [LeetCode]Merge Intervals
  • 原文地址:https://www.cnblogs.com/fxyadela/p/11900771.html
Copyright © 2011-2022 走看看