序列化
什么是序列化:典型的例子,将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'}]> #已经是最新的值了