Django框架中序列化和反序列化的例子


Posted in Python onAugust 06, 2019

1.序列化

DRF的核心 就是 前后端分离的核心

前后端分离开发的核心:

将模型转换为json 称之为 序列化

将json转换为模型 称之为 反序列化

1.序列化器的字段

Serializer 序列化器

为了得到模型里的字段,序列化器中的字段应与模型类中的字段名一致

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  # read_only=True 只能读 不能修改
  id = serializers.IntegerField(read_only=True,label='id')
  name = serializers.CharField(max_length=20,label='书籍名')
  pub_date = serializers.DataField(label='发布日期')
  readcount = serializers.IntegerField()
  is_delete = serializers.BooleanField()
  image = serializers.ImageField()

2.序列化

创建序列器

序列化器的第一个参数:instance 用于序列化操作

序列化器的第二个参数:data 用于反序列化操作

除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如

serializer = AccountSerializer(account, context={'request': request})

通过context参数附加的数据,可以通过Serializer对象的context属性获取。

''' views.py '''

 book = BookInfo.objects.get(id=2)
 
 s = BookInfoSerializers(instance=book)

 # 我们是通过 序列化器的data属性来获取 模型转换为字典的数据
 s.data


 # 传递多个数据
 # 应用: 查询所有书籍列表

 books = BookInfo.objects.all()
 # 创建序列化器,将所有书籍信息传递给序列化器
 # books = [BookInfo,BookInfo,...] 对象列表
 s = BookInfoSerializers(books,many=True)
 
 person = PeopleInfo.objects.get(id=6)

 # 序列化器初始化
 s = PeopleInfoSerializer(instance=person)

3.关联序列化器的操作

对于关联字段,可以采用以下几种方式:

1) PrimaryKeyRelatedField

2) StringRelatedField

3) 使用关联对象的序列化器

#########关联序列化器##########################

 class PeopleInfoSerializer(serializers.Serializer):
  """英雄数据序列化器"""
  GENDER_CHOICES = (
   (0, 'male'),
   (1, 'female')
  )
  id = serializers.IntegerField(label='ID', read_only=True)
  name = serializers.CharField(label='名字', max_length=20)
  gender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别', required=False)
  description = serializers.CharField(label='描述信息', max_length=200, required=False, allow_null=True)


  ''' PrimaryKeyRelatedField '''
  # 设置关联外键的时候,要将 read_only=True
  # 包含read_only=True参数时,该字段将不能用作反序列化使用
  # book = serializers.PrimaryKeyRelatedField(read_only=True,label='外键')
  # 或者
  # 包含queryset参数时,将被用作反序列化时参数校验使用
  # queryset 将关联模型的所有数据传递给这个属性就可以
  book = serializers.PrimaryKeyRelatedField(label='外键',queryset=BookInfo.objects.all())

  '''StringRelatedField'''
  # 现在通过 PrimaryKeyRelatedField得到的是一个 外键的一个值 2
  # 接下来通过 一个设置 来获取 书籍的名字

  # StringRelatedField 可以获取关联模型中的 __str_ 里的字符串
  book = serializers.StringRelatedField()

  ''' 使用关联对象的序列化器 拿到所有数据 '''
  book = BookInfoSerializer()

4.关联查询

关联模型类名小写_set 作为字段名

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  id = serializers.IntegerField(read_only=True,label='id')
  name = serializers.CharFIeld(max_length=20,label='书籍名')
  pub_date = serializers.DataField(label='发布日期')
  readcount = serializers.IntegerField()
  is_delete = serializers.BooleanField()
  iamge = serializers.ImageField()

  
  # 书籍和人物的关系是 1:n ===> many=True
  peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)

  def __str__(self):
   return self.name

2.反序列化

反序列化 分为两个:

数据校验

数据入库

2.1 数据校验

使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。

验证成功,可以通过序列化器对象的validated_data属性获取数据。

在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为

1. 数据校验的第一种方式

在定义序列化器字段的时候,规定是什么类型 就要提交符合规则的数据

例如:DateField 就需要传入符合日期规则的数据

##############将JSON转换为模型 反序列化#############

  ''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  id = serializers.IntegerField(read_only=True,label='id')
  name = serializers.CharFIeld(max_length=20,label='书籍名')
  pub_date = serializers.DataField(label='发布日期')
  
  peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)

  def __str__(self):
   return self.name

 ''' views.py '''

 dict = {
  'name':'itcast',
  'pub_date':'123' # Flase
  # 'pub_date':'2010-1-1' # True
 }

 # 1.创建序列器
 # 序列化器的第一个参数:instance 用于序列化操作
 # 序列化器的第二个参数:data 用于反序列化操作
 serializer = BookInfoSerializer(data=dict)

 # 2.需要调用序列化器的 is_valid 方法 valid验证 返回True False
 # 如果数据可用 返回True
 serializer.is_valid()

 # raise_exception=True 可以设置为True 来抛出异常
 serializer.is_valid(raise_exception=True)

2.数据校验的第二种方式

字段的选项

required : 进行反序列化的时候,必须传这个字段

min_length,max_length 作用于字符串

min_value,max_value 作用于Int整型

default 不传入数据 设置默认值

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  id = serializers.IntegerField(read_only=True,label='id')
  name = serializers.CharFIeld(min_length=5,max_length=20,label='书籍名',)
  pub_date = serializers.DataField(label='发布日期',required=True)


  def __str__(self):
   return self.name

 ''' views.py '''
 dict = {
  'name':'itcast',
  'pub_date':'123' # 若去掉pub_date 则报错
 }

3.数据校验的第三种方式

对单个字段的数据进行验证

语法形式为: 在序列化器中实现方法 def validate_字段名()

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  id = serializers.IntegerField(read_only=True,label='id')
  name = serializers.CharFIeld(min_length=5,max_length=20,label='书籍名',)
  pub_date = serializers.DataField(label='发布日期',required=True)
  readcount = serializers.IntegerField(default=0,required=False)

  def __str__(self):
   return self.name

  def validate_readcount(self,value):
   # value 就是字段传递过来的数据
   if value < 0:
    raise serializers.ValidationError('阅读量不能为负数')

   # 需要将value返回回去
   return value

 ''' views.py '''
 dict = {
  'name':'itcast',
  'readcount':-20, # 报异常
 }

4.数据校验的第四种方式

对多个字段的数据进行验证时

语法形式为: 在序列化器中实现方法 def validate(self,attrs)

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  id = serializers.IntegerField(read_only=True,label='id')
  name = serializers.CharFIeld(min_length=5,max_length=20,label='书籍名',)
  pub_date = serializers.DataField(label='发布日期',required=True)
  readcount = serializers.IntegerField(default=0,required=False)
  commentcount = serializers.IntegerField(default=0,required=False)


  def __str__(self):
   return self.name

  # 对多个字段进行验证
  # def validate(self,attrs):
  def validate(self,data):
   # attrs --> 其实就是data
   readcount = data.get('readcount')
   commentcount = data['commentcount']

   if readcount < commentcount:
    raise serializers.ValidationError('评论量不能大于阅读量')

   # 要将数据返回
   return data


 ''' views.py '''
 # 自定义需求:评论量不能大于阅读量
 dict = {
  'name':'itcast',
  'readcount':20, 
  'commentcount':100
 }

5.数据校验的第五种方式

自定义验证方法

同时给字段添加自定义验证方法

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  # 自定义验证方法
  def custom_validate(self):
   if self == 'admin':
   raise serializers.ValidationError('我就是来捣乱的')

  id = serializers.IntegerField(read_only=True,label='id')
  
  # validators=[] 是给字段 添加自定义验证方法
  name = serializers.CharFIeld(min_length=5,max_length=20,label='书籍名',validators=[custom_validate])
  

  def __str__(self):
   return self.name


 ''' views.py '''
 # 规定:评论量不能大于阅读量
 dict = {
  'name':'itcast',
  'readcount':20, 
  'commentcount':100
 }

2.2 数据入库

6.数据保存 save方法

继承自Serializer的序列化 我们在调用save方法的时候,需要手动实现create方法,

调用save方法之前,必须调用 is_valid方法,

即 要想保存数据,必须保证数据是经过校验的。

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  def create(self,validated_data):

   # dict --> data --> attrs --> validated_data
   # validated_data 此处其实就是views.py中的dict
   # validated_data 已经被验证过的数据

   # * 对列表进行解包 *list
   # ** 对字典进行解包 **dict
   # 此处解包 将dict中的值 赋值给对象中的对应字段
   book = BookInfo.objects.create(**validated_data)

   # create 需要将创建的对象返回
   return book 



  ''' views.py '''

 # 规定:评论量不能大于阅读量
 dict = {
  'name':'itcast',
  'readcount':20, 
  'commentcount':100
 } 



 serializer = BookInfoSerializer(data=dict)
 serializer.is_valid(raise_exception=True)

 # 3. 保存需要调用序列化器的save方法
 # 继承自Serializer的序列化 我们在调用save方法的时候,需要手动实现create方法
 serializer.save()

7.序列化器中传入两个参数,即数据的更新操作

如果我们在序列化器中既传入了对象,又传入了数据

系统会认为我们在更新数据

继承自Serializer的类,要更新数据的时候,需要手动实现update方法

''' serializers.py '''

 class BookInfoSerializer(serializers.Serializer):

  def update(self,instance,validated_data):
   # instance : 就是我们在更新数据时,传入序列化器的对象
   # validated_data : 验证之后的数据

   instance.name = validated_data.get('name',instance.name)
   instance.pub_date = validated_data.get('pub_date',instance.pub_date)
   instance.readcount = validated_data.get('readcount',instance.readcount)
   instance.commentcount = validated_data.get('commentcount',instance.commentcount)

   instance.save()

   # update()方法需要我们手动返回对象
   return instance
   


 '''views.py '''

 # 1.获取对象
 book = BookInfo.objects.get(id=2)
 # 2.保存数据
 data = {
  'name':'lalala',
  'pub_date':'2018-1-1',
  'readcount':1000,
  'commentcount':10
 } 

 # 3.创建序列化器
 s = BookInfoSerializer(instance=book,data=data)
 # 4.验证数据
 s.is_valid(raise_exception=True)
 # 5.保存数据
 s.save()

3.ModelSerializer

如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

ModelSerializer与常规的Serializer相同,但提供了:

基于模型类自动生成一系列字段

包含默认的create()和update()的实现

''' serializers.py '''

 class BookSerializer(serializers.ModelSerializer):
  
  # 如何设置 通过class Meta
  class Meta:
   model = BookInfo # 设置关联模型  model就是关联模型
   # fields = '__all__' # fields设置字段 __all__表示所有字段
   # fields = ['id','name','pub_date'] # fields设置字段 []列表显示来设置
   exclude = ['image'] # exclude 排除列表中的字段,剩余的字段都显示

   read_only_fields = ('id','readcount','commentcount')

   # 我们可以对自动生成的字段 进行额外的设置
   extra_kwargs = {
    # 字段名:{选项:值}
    'pub_date':{'required':True},
    'readcount':{
     'max_value':10000,
     'min_value':0
    }
   }

 '''views.py'''

 #########ModelSerializer##############
 data = {
   'name':'abc',
   'pub_date':'2018-1-1',
   'readcount':1000,
   'commentcount':10
  } 

 s = BookSerializer(data=data)
 s.is_valid(raise_exception=True)
 s.save()

以上这篇Django框架中序列化和反序列化的例子就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
跟老齐学Python之有容乃大的list(3)
Sep 15 Python
Python 多进程和数据传递的理解
Oct 09 Python
python爬虫爬取某站上海租房图片
Feb 04 Python
全面分析Python的优点和缺点
Feb 07 Python
python3结合openpyxl库实现excel操作的实例代码
Sep 11 Python
python爬取cnvd漏洞库信息的实例
Feb 14 Python
pytorch torch.expand和torch.repeat的区别详解
Nov 05 Python
python模式 工厂模式原理及实例详解
Feb 11 Python
解决Jupyter无法导入已安装的 module问题
Apr 17 Python
Python在字符串中处理html和xml的方法
Jul 31 Python
浅谈Python3中print函数的换行
Aug 05 Python
python3.7.2 tkinter entry框限定输入数字的操作
May 22 Python
python异常触发及自定义异常类解析
Aug 06 #Python
Python DataFrame一列拆成多列以及一行拆成多行
Aug 06 #Python
Django中reverse反转并且传递参数的方法
Aug 06 #Python
matplotlib命令与格式之tick坐标轴日期格式(设置日期主副刻度)
Aug 06 #Python
python+openCV调用摄像头拍摄和处理图片的实现
Aug 06 #Python
对Django 转发和重定向的实例详解
Aug 06 #Python
django 环境变量配置过程详解
Aug 06 #Python
You might like
PHP生成等比缩略图类和自定义函数分享
2014/06/25 PHP
PHP设计模式之工厂模式实例总结
2017/09/01 PHP
PHP实现的微信公众号扫码模拟登录功能示例
2019/05/30 PHP
laravel 创建命令行命令的图文教程
2019/10/23 PHP
jQuery使用手册之二 DOM操作
2007/03/24 Javascript
Javascript+XMLHttpRequest+asp.net无刷新读取数据库数据
2009/08/09 Javascript
为javascript添加String.Format方法
2020/08/11 Javascript
一个原生的用户等级的进度条
2010/07/03 Javascript
如何获取JQUERY AJAX返回的JSON结果集实现代码
2012/12/10 Javascript
javascript列表框操作函数集合汇总
2013/11/28 Javascript
js 动态加载事件的几种方法总结
2013/12/25 Javascript
微信jssdk在iframe页面失效问题的解决措施
2016/03/03 Javascript
Angular2学习笔记——详解路由器模型(Router)
2016/12/02 Javascript
JS异步错误捕获的一些事小结
2019/04/26 Javascript
了不起的11个JavaScript代码重构最佳实践小结
2021/01/11 Javascript
JavaScript仿京东轮播图效果
2021/02/25 Javascript
[03:40]DOTA2抗疫特别篇《英雄年代》
2020/02/28 DOTA
在Python中使用cookielib和urllib2配合PyQuery抓取网页信息
2015/04/25 Python
Python实现的HTTP并发测试完整示例
2020/04/23 Python
在Python的Flask框架中验证注册用户的Email的方法
2015/09/02 Python
python 列表,数组和矩阵sum的用法及区别介绍
2018/06/28 Python
python打印9宫格、25宫格等奇数格 满足横竖斜相加和相等
2019/07/19 Python
python list多级排序知识点总结
2019/10/23 Python
html5 canvas的绘制文本自动换行的示例代码
2018/09/17 HTML / CSS
沙龙级头发造型工具:FOXYBAE
2018/07/01 全球购物
美国单身专业人士在线约会网站:EliteSingles
2019/03/19 全球购物
.NET面试题:什么是值类型和引用类型
2016/01/12 面试题
小学生自我鉴定
2013/10/12 职场文书
计算机学生的自我评价分享
2014/02/18 职场文书
审计专业自荐信范文
2014/04/21 职场文书
应届本科毕业生求职信
2014/07/23 职场文书
离职证明范本(5篇)
2014/09/19 职场文书
导游词格式
2015/02/13 职场文书
住房公积金贷款工资证明
2015/06/12 职场文书
2016年学生会感恩节活动总结
2016/04/01 职场文书
Python爬虫数据的分类及json数据使用小结
2021/03/29 Python