zoukankan      html  css  js  c++  java
  • DRF__序列化(1)serializers.Serializer 基本的序列化、反序列化概念

    序列化

    什么是序列化:典型的例子,将django中的模型实例类型,转换成json供前端去展示

    最基本的序列化方法 serializers.Serializer

    存在模型类如下:

    from django.db import models
    
    class Person(models.Model):
      name = models.CharField(max_length=50)
      gender = (('男','M'),('女','f'))
      sex = models.CharField(choices=gender,max_length=50)
      remarks = models.TextField()
      class Meta:
        db_table = 'person'
      def __str__(self):
        return self.name
    

    这时候需要根据模型类写对应的序列化类,新建文件serializers.py用来存放所以的序列化类
    新建PersonSerializers类如下:

    from rest_framework import serializers
    
    class PersonSerializers(serializers.Serializer):
      name = serializers.CharField(max_length=50)
      sex = serializers.CharField(max_length=50)
      
    

    看出写序列化类的时候,和写models类的时候十分相似(和写forms表单类也相似)

    这时候开始序列化字段,进入 django shell : python manage.py shell

    >>> from drf.models import Person
    >>> from drf.serializers import PersonSerializers
    >>> person = Person.objects.create(name='kobe',sex='M',remarks='科比布莱恩特') #声明一个模型实例
    >>> ser = PersonSerializers(person) #序列化传入的实例
    >>> ser.data
    {'name': 'kobe', 'sex': 'M', 'remarks': '科比布莱恩特'}  ### 这时候就已经转换成一个字典类型的数据了
    >>> ser
    PersonSerializers(<Person: kobe>):
        name = CharField(max_length=50)
        sex = CharField(max_length=50)
        remarks = CharField()
    >>> type(ser)
    <class 'drf.serializers.PersonSerializers'>
    >>> type(ser.data)
    <class 'rest_framework.utils.serializer_helpers.ReturnDict'>   
    
    

    转换成字典之后,还想要转换成json格式,接着上述的shell中执行

    >>> from rest_framework.renderers import JSONRenderer
    >>> jsondata = JSONRenderer().render(ser.data)
    >>> jsondata
    b'{"name":"kobe","sex":"M","remarks":"xe7xa7x91xe6xafx94xe5xb8x83xe8x8exb1xe6x81xa9xe7x89xb9"}'
    >>> jsondata.decode('utf-8')
    '{"name":"kobe","sex":"M","remarks":"科比布莱恩特"}'
    

    如果传递到序列化类中的不是一个模型实例,而是一个查询集queryset,要怎么处理?
    还是接着上述的shell中执行

    >>> query = Person.objects.filter(id=1)
    >>> query
    <QuerySet [<Person: kobe>]>
    >>> ser = PersonSerializers(query)
    >>> ser
    PersonSerializers(<QuerySet [<Person: kobe>]>): ##注意和之前的区分,之前是实例,这里注明了是queryset
        name = CharField(max_length=50)
        sex = CharField(max_length=50)
        remarks = CharField()
    ###这时候如果  ser.data  会报错 AttributeError: 'QuerySet' object has no attribute 'name'
    

    正确的处理方式是

    >>> ser = PersonSerializers(query,many=True)
    >>> ser.data
    [OrderedDict([('name', 'kobe'), ('sex', 'M'), ('remarks', '科比布莱恩特')])]
    

    同时带出另外一个问题,如果要一次性序列化多个,这里就要用到many=True这个参数了

    >>> person = Person.objects.create(name='james',sex='M',remarks='勒布朗詹姆斯')  ##先增加一个测试数据
    >>> query = Person.objects.all()
    >>> query
    <QuerySet [<Person: kobe>, <Person: james>]>
    >>> ser = PersonSerializers(query,many=True)   ###many=True必须要
    >>> ser.data   #返回的是一个序列化的列表
    [OrderedDict([('name', 'kobe'), ('sex', 'M'), ('remarks', '科比布莱恩特')]), OrderedDict([('name', 'james'), ('sex', 'M'), ('remarks', '勒布朗詹姆斯')])]
    
    
    >>> jsondata = JSONRenderer().render(ser.data)
    >>> jsondata
    b'[{"name":"kobe","sex":"M","remarks":"xe7xa7x91xe6xafx94xe5xb8x83xe8x8exb1xe6x81xa9xe7x89xb9"},{"name":"james","sex":"M","remarks":"xe5x8bx92xe5xb8x83xe6x9cx97xe8xa9xb9xe5xa7x86xe6x96xaf"}]
    

    总结:

    • 序列化类(模型实例) 返回一个drf序列化对象
    • 序列化对象.data 返回一个字典类型
    • 导入 rest_framework.renderers import JSONRenderer,然后 JSONrenderer().render(序列化对象.data) 返回一个bytes的json数据,到此序列化完成
    • 一般序列化的是一个模型实例,如果要序列化查询集,或者需要一次性序列化多个内容 需要添加 many=True

    反序列化

    上面讲了序列化,一般是用在查询的时候,如果要根据前端传递来的数据 新增模型实例,以及修改模型实例中的一些字段呢? 这时候就需要将传递过来的数据类型转换为django中的数据类型,这就是反序列化

    一般处理request的数据时候,是需要通过 JSONParser().parse()先解析为字典的 from rest_framework.parsers import JSONParser,这里测试直接从字典开始反序列化

    >>> data = {'name':'paul','sex':'M'}
    >>> ser = PersonSerializers(data=data)
    >>> ser.is_valid()   #如果数据没有通过校验,是不允许save的
    False
    >>> ser.save()
    ###报错: AssertionError: You cannot call `.save()` on a serializer with invalid data.
    
    
    
    >>> data = {'name':'paul','sex':'M','remarks':'585858'}
    >>> ser = PersonSerializers(data=data)
    >>> ser.is_valid()  #这一步是必须的,反序列化必须检验 数据是否符合要求
    True
    >>> ser.save()   
    ###报错: NotImplementedError: `create()` must be implemented.
    

    上面报错了,create() 方法必须执行,然后我们的序列化类PersonSerializers中并没有这个方法,所以需要手动添加这个方法,修改序列化类如下:

    class PersonSerializers(serializers.Serializer):
        name = serializers.CharField(max_length=50)
        sex = serializers.CharField(max_length=50)
        remarks = serializers.CharField()
    
        ###当只传入  data=*** 时候  save()调用的是新增
        def create(self,validated_data):
            return Person.objects.create(**validated_data)
        
        ###当传入一个实例,并传入一个data=*** 的时候  save()调用的是修改
        def update(self,instance,validated_data):
            instance.name = validated_data.get('name')
            instance.sex = validated_data.get('sex')
            instance.remarks = validated_data.get('remarks')
            instance.save() #这个save是指模型实例更新字段后的save,不是上面说的那个序列化类的save
            return instance
    
    

    这时候在测试如下新增:

    >>> data = {'name':'paul','sex':'M','remarks':'585858'}
    >>> ser = PersonSerializers(data=data)
    >>> ser.is_valid()
    True
    >>> ser.validated_data
    OrderedDict([('name', 'paul'), ('sex', 'M'), ('remarks', '585858')])
    >>> ser.save()  ### 调用了create方法
    <Person: paul>  ### 查询数据库中 新增了这么一个对象
    

    然后再测试一下修改:

    >>> instance = Person.objects.get(id=3)
    >>> instance.name
    'paul'
    >>> instance.remarks
    '585858'
    >>> data = {'name':'paulxxx','sex':'M','remarks':'999'}
    >>> ser = PersonSerializers(instance=instance,data=data)
    >>> ser.is_valid()
    True
    >>> ser.save()
    <Person: paulxxx>   #这时候返回的就是 update中返回的instance 看出已经修改成功
    
    
    #验证一下:
    >>> queryset = Person.objects.filter(id=3)
    >>> queryset.values()
    <QuerySet [{'id': 3, 'name': 'paulxxx', 'sex': 'M', 'remarks': '999'}]>  #已经是最新的值了
    
  • 相关阅读:
    Jenkins+Ansible+Gitlab自动化部署三剑客(四)--Jenkins Linux shell集成
    Jenkins+Ansible+Gitlab自动化部署三剑客(三)--Jenkins
    腾讯云从业者线上课程(一)--云计算技术架构
    腾讯云从业者线上课程(一)--云计算发展历史
    nmcli 静态方式添加IP地址
    nmcli
    systemctl 控制单元
    ansible组件 Ad-Hoc
    ansible 定义主机用户和密码
    ansible 主机清单 /etc/ansible/hosts
  • 原文地址:https://www.cnblogs.com/alantammm/p/14518115.html
Copyright © 2011-2022 走看看