Django 序列化和反序列化(九)
一、什么是序列化和反序列化?
将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例如将Django中的模型类对象装换为JSON字符串,这个转换过程我们称为序列化。
反之,将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串转换为Django中的模型类对象,这个过程我们称为反序列化。
序列化器类,在Serializer.py文件中:
#继承Serializer:处理序列化的,可以进行校验; (但必须要使用BookInfo模型类中所有的字段)
class BookInfoserializer(serializers.Serializer):'''图书数据序列化器'''# 表明该字段仅用于序列化输出,默认Falseid=serializers.IntegerField(label='ID',read_only=True)name=serializers.CharField(label='名称',max_length=20)# 表明该字段在反序列化时必须输入,默认Truepub_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
<BookInfo: 射雕英雄传>
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
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> 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除外键字段外的其他部分
- PrimaryKeyRelatedField:此字段将被序列化为关联对象的主键。默认是将关联模型的id序列化
- StringRelatedField:此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)
##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<CustomerInfo: 郭靖>>>> 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',
- , ('image', '/book/5.jpg')]), 'is_del': False}
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):'''图书数据序列化器'''# 表明该字段仅用于序列化输出,默认Falseid=serializers.IntegerField(label='ID',read_only=True)name=serializers.CharField(label='名称',max_length=20)# 表明该字段在反序列化时必须输入,默认Truepub_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 bookdef 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()
<BookInfo: pythons2>
再使用另一个终端查看数据库:
(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()
<BookInfo: pythons1>
三、模型类序列化器ModelSerializer
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)
>>>
Django 序列化和反序列化(九)相关推荐
- Django——序列化与反序列化
目录 Serializer类 序列化 反序列化 模型类序列化器BookModelSerializer Serializer类 1.定义: Django REST framework中的Serializ ...
- Django restful Framework 之序列化与反序列化
1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...
- Django Rest Framework 1:序列化与反序列化
文章目录 一,开发准备 1,创建django项目tutorial 2,创建应用snippet 3,安装DRF 4,配置settings.py 5,创建模型Snippet 6,数据迁移 二,使用 Ser ...
- Django的序列化和反序列化
在开发REST API接口时,视图中做的最主要有三件事: 将请求的数据(如JSON格式)转换为模型类对象 操作数据库 将模型类对象转换为响应的数据(如JSON格式) 序列化可以理解为: 将程序中的一个 ...
- django中序列化、反序列化过程
一.定义序列化器 a.如果需要使用DRF框架来实现序列化.反序列化.数据库操作,在子应用中创建serializers.py文件 b.文件名推荐命名为serializers.py 在serializer ...
- C++实现二叉树相关问题(先序遍历,中序遍历,后序遍历,层序遍历,搜索二叉树、平衡二叉树、满二叉树、完全二叉树的判断,最低公共祖先,二叉树的序列化和反序列化)
目录 题目一 二叉树递归和非递归遍历 题目二 如何完成二叉树的宽度(也叫层序)遍历(常见题目:求一棵二叉树的宽度) 题目四 如何判断一棵二叉树是搜索二叉树(BST)? 题目四 如何判断一棵二叉树是平衡 ...
- (13)C#传智:访问修饰符,简单工厂模式,序列化与反序列化,部分类,密封类,接口(第13天)
内容超级多,慢慢来... 深入BinaryFormatter 一.访问修饰符 public: 公共的,公开的 private:私有的,只能在当前类的内部访问 protected:受保持 ...
- Unity中的序列化和反序列化
一:前言 序列化是指把对象转换为字节序列的过程,而反序列化是指把字节序列恢复为对象的过程.序列化最主要的用途就是传递对象和保存对象 在Unity中保存和加载.prefab.scene.Inspecto ...
- python文件IO二--序列化和反序列化
内存中的字典.链表.列表如何保存到文件中? 自定义的类的实例,如何保存到文件中? 又怎么读取才能让他们在内存中再次变成自己对应的类的实例? 这就是序列化和反序列化 一.理解(serialization ...
最新文章
- 【AI竞赛】TinyMind汉字书法识别挑战赛开始报名啦!!
- 大厂程序媛的特殊烦恼:男朋友工资只有自己的60%,天天阴阳怪气!
- SAP SD-如何控制定价折扣的总额度
- python实现项目的复制_Python之copy模块
- 树莓派进阶之路 (037) - 设置树莓派3 B+的静态IP
- webwork 标签 基本用法 例子
- 计算机配置选项在哪,电脑启动项目设置在哪
- XgBoost使用及调参教程
- 使用log4Net 输出日志到mongodb
- 力扣--8字符串转换整数 (atoi)
- Memcache分组和同步机制的实现
- 一步一步学Ruby(八):字符串表达式
- 万能显卡驱动win7_驱动工具更新!完美支持苹果电脑驱动
- 三种1:4传输线变压器巴伦的分析
- 云孚开源情报系统YFINT
- php开发数独,数独解题小程序实现代码
- java迭代例子_Java 迭代器的代码实例详解
- uestc 1903
- 如何在微信小程序中实现实时会话(聊天)系统
- 139邮箱smtp地址和端口_常用的邮箱服务器(SMTP、POP3)地址、端口