DRF__序列化(1)serializers.Serializer 基本的序列化、反序列化概念 序列化 反序列化

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'}]>  #已经是最新的值了