一、什么是序列化和反序列化?
将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例如将Django中的模型类对象装换为JSON字符串,这个转换过程我们称为序列化。
反之,将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串转换为Django中的模型类对象,这个过程我们称为反序列化。
序列化器类,在Serializer.py文件中:
#继承Serializer:处理序列化的,可以进行校验; (但必须要使用BookInfo模型类中所有的字段)
class BookInfoserializer(serializers.Serializer):
'''图书数据序列化器'''
# 表明该字段仅用于序列化输出,默认False
id=serializers.IntegerField(label='ID',read_only=True)
name=serializers.CharField(label='名称',max_length=20)
# 表明该字段在反序列化时必须输入,默认True
pub_date=serializers.DateField(label='发布日期',required=False)
read_count=serializers.IntegerField(label='阅读量',required=False)
comment_count=serializers.IntegerField(label='评论量',required=False)
is_delete=serializers.BooleanField(label='逻辑删除',required=False)
image=serializers.ImageField(label='图片',required=False)
在终端进行测试:
1.序列化器做序列化处理
1) 先查询出一个图书对象
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>>from books.models import BookInfo
>>> book=BookInfo.objects.get(id=1)
>>> book
2) 构造序列化器对象
>>> from books.Serializer import BookInfoserializer
>>> serializer=BookInfoserializer(book)
3) 获取序列化数据
>>> serializer.data
{'id': 1, 'name': '射雕英雄传', 'pub_date': '1980-05-01', 'read_count': 12, 'comment_count': 34, 'image': '/book/5.jpg'}
4) 如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加**many=True**参数补充说明
>>> from books.models import BookInfo
>>> book_find=BookInfo.objects.all()
>>> book_find
>>> from books.Serializer import BookInfoserializer
>>> serializer=BookInfoserializer(book_find,many=True)
>>> serializer.data
[OrderedDict([('id', 1), ('name', '射雕英雄传'), ('pub_date', '1980-05-01'), ('read_count', 12), ('comment_count', 34), ('image', '/book/5.jpg')]), OrderedDict([('id', 2), ('name', '天
龙八部'), ('pub_date', '1986-07-24'), ('read_count', 36), ('comment_count', 40), ('image', None)]), OrderedDict([('id', 3), ('name', '笑傲江湖'), ('pub_date', '1995-12-24'), ('read_cou
nt', 20), ('comment_count', 80), ('image', '/book/4.jpg')]), OrderedDict([('id', 4), ('name', '雪山飞狐'), ('pub_date', '1987-11-11'), ('read_count', 58), ('comment_count', 24), ('imag
e', '/book/1.jpg')])]
2.关联对象序列化
如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。
例如,在定义英雄数据的序列化器时,外键book(即所属的图书)字段如何序列化?
我们先定义CustomerInfoSerialzier除外键字段外的其他部分
##ModelSerializer:序列化的封装,不能进行校验;
class CustomerInfoSerializer(serializers.ModelSerializer):
'''
人物序列化器操作
'''
id=serializers.IntegerField(label='ID',read_only=True)
name=serializers.CharField(label='姓名',max_length=20)
gender=serializers.IntegerField(label='性别',required=False)
detail=serializers.CharField(label='描述',required=False)
#第一种方式:将序列化的对象做为主键,默认将关联的模型id序列化
# book=serializers.PrimaryKeyRelatedField(label='图书',read_only=True)
#第二种方式:将字段序列化为关联对象的主键,
book=serializers.StringRelatedField(label='图书',read_only=True)
is_delete = serializers.BooleanField(label='逻辑删除', required=False)
class Meta:
model=CustomerInfo #指定序列化模型类
fields='__all__'
#第一种方式:将序列化的对象做为主键,默认将关联的模型id序列化# book=serializers.PrimaryKeyRelatedField(label='图书',read_only=True)
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>> from books.models import CustomerInfo
>>> customer=CustomerInfo.objects.get(id=1)
>>> customer
>>> from books.Serializer import CustomerInfoSerializer
>>> serializer=CustomerInfoSerializer(customer)
>>> serializer.data
{'id': 1, 'name': '郭靖', 'gender': 1, 'detail': '降龙十八掌', 'book': 1, 'is_del': False}
第二种方式: book=serializers.StringRelatedField(label='图书',read_only=True)
>>> from books.models import CustomerInfo
>>> from books.Serializer import CustomerInfoSerializer
>>> cs=CustomerInfo.objects.get(id=6)
>>> c=CustomerInfoSerializer(cs)
>>> c.data
{'id': 6, 'name': '乔峰', 'gender': 1, 'detail': '降龙十八掌', 'book': '天龙八部', 'is_del': False}
3.使用关联对象的序列化器
在终端进行测试:
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>> from books.Serializer import CustomerInfoSerializer
>>> from books.models import CustomerInfo
>>> cs=CustomerInfo.objects.get(id=1)
>>> serializer=CustomerInfoSerializer(cs)
>>> serializer.data
{'id': 1, 'name': '郭靖', 'gender': 1, 'detail': '降龙十八掌', 'book': OrderedDict([('id', 1), ('name', '射雕英雄传'), ('pub_date', '1980-05-01'), ('read_count', 12), ('comment_count',
4. many参数
关联只能一个关联另一个,不能两个互相关联,所以在使用Book关联Customer时要把Customer对Book的关联去掉
如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的人物CustomerInfo对象可能有多个,此时关联字段类型的指明仍可使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数即可。
此处仅拿PrimaryKeyRelatedField类型来举例,其他相同。
注意字段命名为**关联对象名_set**
在BookInfoSerializer中添加关联字段:
在终端进行测试:
>>> from books.Serializer import BookInfoSerializer
>>> from books.models import BookInfo
>>> book=BookInfo.objects.get(id=1)
>>> serializer=BookInfoSerializer(book)
>>> serializer.data
{'id': 1, 'name': '射雕英雄传', 'pub_date': '1980-05-01', 'read_count': 12, 'comment_count': 34, 'is_del': False, 'image': '/book/5.jpg'}
序列化步骤总结
1.定义序列化器类(模型名/类视图名 Serializer)继承 Serializer
2.定义序列化性中的字段参照模型(序列化中的字段可以比模型多或少如果表示是模型中的字段在序列化中这个字段名应读和模型中字段名一致)
3.如果在多里面关联序列化(外健) ,如果是在一里面关联序列化多(多的一方模型名小写_set)
4.如果在一的一方关联序列化多时,需要指定关联字段 many=True
5.将要序列化模型或查询集传给序列化器类的instance,参数如果传的是查询集多指定many=Ture
6.获取序列化后的数据: 序列化器对象.data属性
(1) 数据校验
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
(1) 验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
(2) 验证成功,可以通过序列化器对象的validated_data属性获取数据。
在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为
class BookInfoserializer(serializers.ModelSerializer):
'''图书数据序列化器'''
# 表明该字段仅用于序列化输出,默认False
id=serializers.IntegerField(label='ID',read_only=True)
name=serializers.CharField(label='名称',max_length=20)
# 表明该字段在反序列化时必须输入,默认True
pub_date=serializers.DateField(label='发布日期',required=False)
read_count=serializers.IntegerField(label='阅读量',required=False)
comment_count=serializers.IntegerField(label='评论量',required=False)
is_delete=serializers.BooleanField(label='逻辑删除',required=False)
image=serializers.ImageField(label='图片',required=False)
1.通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进行验证
2.使用.is_valid()进行校验 True
3.validated_data获取反序列化校验后的数据还是字典
4.保存
反序列化操作步骤 在终端进行测试:
(djg2021) E:\appDjango\mydjg1>python manage.py shell
#导入序列化器
>>>from books.Serializer import BookInfoserializer
#传入数据
>>> data = {'name':'python'}
#构造序列化对象
>>>ser=BookInfoserializer(data=data)
#进行校验 True
>>> ser.is_valid()
#获取反序列化校验后的数据->有序dict字典
>>>ser.validated_data
返回:OrderedDict([('name', 'python')])
is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,
可以通过传递**raise_exception=True**参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
>>> ser.is_valid(raise_exception=True)
raise_exception 启动序列化报错的方法
#### 获取校验的错误信息#### {}
ser.errors
(2)数据入库
数据保存 save方法 ,要更新数据的时候,需要手动实现update方法
继承自Serializer的序列化 我们在调用save方法的时候,需要手动实现create方法,
调用save方法之前,必须调用 is_valid方法,即 要想保存数据,必须保证数据是经过校验的。
class BookInfoserializer(serializers.Serializer):
'''图书数据序列化器'''
# 表明该字段仅用于序列化输出,默认False
id=serializers.IntegerField(label='ID',read_only=True)
name=serializers.CharField(label='名称',max_length=20)
......
def create(self, validated_data):
'''
添加
:param validated_data:
:return:
'''
#获取数据保存到模型类中(缓存) -->没有保存到数据库中
book=BookInfo(**validated_data)
return book
def update(self, instance, validated_data):
'''
更新
:param instance: 更新的对象
:param validated_data:
:return:
'''
#获取数据,再校验
instance.name=validated_data.get('name',instance.name)
instance.pub_date=validated_data.get('pub_date',instance.pub_date)
instance.read_count=validated_data.get('read_count',instance.read_count)
instance.comment_count=validated_data.get('comment_count',instance.comment_count)
#保存
instance.save()
return instance
使用终端测试:
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>> from books.Serializer import BookInfoserializer
>>> data={'name':'pythons2'}
>>> ser=BookInfoserializer(data=data)
>>> ser.is_valid()
True
>>> ser.validated_data
OrderedDict([('name', 'pythons2')])
>>> ser.save()
再使用另一个终端查看数据库:
(djg2021) E:\appDjango>mysql -h 8.136.181.55 -uusers -p369985
mysql> show databases;
mysql> use hlx;
mysql> select * from bookinfo;
+----+------------+------------+------------+---------------+--------+------------+
| id | name | pub_date | read_count | comment_count | is_del | image |
+----+------------+------------+------------+---------------+--------+------------+
| 1 | 射雕英雄传 | 1980-05-01 | 12 | 34 | 0 | book/5.jpg |
| 2 | 天龙八部 | 1986-07-24 | 36 | 40 | 0 | NULL |
| 3 | 笑傲江湖 | 1995-12-24 | 20 | 80 | 0 | book/4.jpg |
| 4 | 雪山飞狐 | 1987-11-11 | 58 | 24 | 0 | book/1.jpg |
+----+------------+------------+------------+---------------+--------+------------+
(3)ModelSerializer
使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer相同,但提供了:
(1) 基于模型类自动生成一系列字段
(2) 包含默认的create()和update()的实现
class BookInfoserializer(serializers.ModelSerializer):
其他的相同...
#必须要这个Meta类
class Meta:
model = BookInfo # 指定序列化模型类
fields = '__all__'
使用终端测试:
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>> from books.Serializer import BookInfoserializer
>>> data={'name':'pythons1'}
>>> ser=BookInfoserializer(data=data)
>>> ser.is_valid()
True
>>> ser.validated_data
OrderedDict([('name', 'pythons1')])
>>> ser.save()
2.1 定义
#1. ModelSerializer:序列化的封装,不能进行校验;
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model=BookInfo #指定序列化模型类
fields='__all__'
使用终端查看:
>>> from books.Serializer import BookInfoSerializer
>>> ser=BookInfoSerializer()
>>> ser
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
pub_date = DateField(allow_null=True, label='分布日期', required=False)
read_count = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
comment_count = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_del = BooleanField(label='逻辑删除', required=False)
image = ImageField(allow_null=True, label='图片', max_length=100, required=False)
>>>
2.2 指定字段
(1) 使用**fields**来明确字段,`__all__`表名包含所有字段,也可以写明具体哪些字段,如
#1. ModelSerializer:序列化的封装,不能进行校验;
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model=BookInfo #指定序列化模型类
fields=('id','name','pub_date') #获取部分字段
使用终端查看:
>>> from books.Serializer import BookInfoSerializer
>>> ser=BookInfoSerializer()
>>> ser
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
pub_date = DateField(allow_null=True, label='分布日期', required=False)
>>>
(2) 使用**exclude**可以明确排除掉哪些字段
#1. ModelSerializer:序列化的封装,不能进行校验;
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model=BookInfo #指定序列化模型类
#排除指定的字段
exclude=('image',) #注意必须加",",不能fields一起使用哦!!!
使用终端查看:
>>> from books.Serializer import BookInfoSerializer
>>> ser=BookInfoSerializer()
>>> ser
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
pub_date = DateField(allow_null=True, label='分布日期', required=False)
read_count = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
comment_count = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_del = BooleanField(label='逻辑删除', required=False)
>>>
(3) 默认ModelSerializer使用主键作为关联字段,但是我们可以使用**depth**来简单的生成嵌套表示,depth应该是整数,表明嵌套的层级数量。如:
#1. ModelSerializer:序列化的封装,不能进行校验;
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model=BookInfo #指定序列化模型类
fields='__all__' #获取所有的数据字段
#生成表的形式
depth=1
使用终端查看:
(djg2021) E:\appDjango>cd mydjg1
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>> from books.Serializer import BookInfoSerializer
>>> ser=BookInfoSerializer()
>>> ser
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
pub_date = DateField(allow_null=True, label='分布日期', required=False)
read_count = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
comment_count = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_del = BooleanField(label='逻辑删除', required=False)
image = ImageField(allow_null=True, label='图片', max_length=100, required=False)
>>>
(4) 指明只读字段
可以通过**read_only_fields**指明只读字段,即仅用于序列化输出的字段
#1. ModelSerializer:序列化的封装,不能进行校验;
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model=BookInfo #指定序列化模型类
fields=('id','name','pub_date') #获取部分字段
#指定为只读字段
read_only_fields=('id','name')
使用终端查看:
(djg2021) E:\appDjango>cd mydjg1
(djg2021) E:\appDjango\mydjg1>python manage.py shell
>>> from books.Serializer import BookInfoSerializer
>>> ser=BookInfoSerializer()
>>> ser
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', read_only=True)
pub_date = DateField(allow_null=True, label='分布日期', required=False)
2.3添加额外参数
使用**extra_kwargs**参数为ModelSerializer添加或修改原有的选项参数
#1. ModelSerializer:序列化的封装,不能进行校验;
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model=BookInfo #指定序列化模型类
#必须要有这个字段哦!!read_count','comment_count
fields = ('id', 'name', 'pub_date','read_count','comment_count')
#添加额外的参数
extra_kwargs={
'read_count': {'min_value': 10, 'required': True},
'comment_count': {'min_value': 10, 'required': True},
}
使用终端查看:
>>> from books.Serializer import BookInfoSerializer
>>> ser=BookInfoSerializer()
>>> ser
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
pub_date = DateField(allow_null=True, label='分布日期', required=False)
read_count = IntegerField(label='阅读量', max_value=2147483647, min_value=10, required=True)
comment_count = IntegerField(label='评论量', max_value=2147483647, min_value=10, required=True)
>>>