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 相关文章推荐
Django框架中的对象列表视图使用示例
Jul 21 Python
搭建Python的Django框架环境并建立和运行第一个App的教程
Jul 02 Python
ansible作为python模块库使用的方法实例
Jan 17 Python
Python 专题一 函数的基础知识
Mar 16 Python
浅谈flask源码之请求过程
Jul 26 Python
python里 super类的工作原理详解
Jun 19 Python
pygame库实现俄罗斯方块小游戏
Oct 29 Python
python实现遍历文件夹图片并重命名
Mar 23 Python
浅谈keras中的目标函数和优化函数MSE用法
Jun 10 Python
Python3 webservice接口测试代码详解
Jun 23 Python
Python3爬虫RedisDump的安装步骤
Feb 20 Python
python数字图像处理之图像自动阈值分割示例
Jun 28 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 为例)
2019/10/30 PHP
javascript抖动元素的小例子
2013/10/28 Javascript
jQuery制作仿Mac Lion OS滚动条效果
2015/02/10 Javascript
javascript实现tab切换特效
2015/11/12 Javascript
使用Javascript实现选择下拉菜单互移并排序
2016/02/23 Javascript
详谈jQuery.load()和Jsp的include的区别
2017/04/12 jQuery
js如何编写简单的ajax方法库
2017/08/02 Javascript
使用html+js+css 实现页面轮播图效果(实例讲解)
2017/09/21 Javascript
vue-rx的初步使用教程
2018/09/21 Javascript
vue项目刷新当前页面的三种方法
2018/12/04 Javascript
JS实现的冒泡排序,快速排序,插入排序算法示例
2019/03/02 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
python3模拟百度登录并实现百度贴吧签到示例分享(百度贴吧自动签到)
2014/02/24 Python
Python通过解析网页实现看报程序的方法
2014/08/04 Python
详解Python中for循环的使用方法
2015/05/14 Python
深入理解Python中各种方法的运作原理
2015/06/15 Python
Python Series从0开始索引的方法
2018/11/06 Python
Python 处理图片像素点的实例
2019/01/08 Python
python实现比较类的两个instance(对象)是否相等的方法分析
2019/06/26 Python
Python递归函数 二分查找算法实现解析
2019/08/12 Python
Python爬虫之Selenium设置元素等待的方法
2020/12/04 Python
HTML5全屏(Fullscreen)API详细介绍
2015/04/24 HTML / CSS
如何整合JQuery和Prototype
2014/01/31 面试题
JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
2013/07/02 面试题
应届生程序员求职信
2013/11/05 职场文书
单位未婚证明范本
2014/01/18 职场文书
《云雀的心愿》教学反思
2014/02/25 职场文书
安踏广告词改编版
2014/03/21 职场文书
幼儿园户外活动总结
2014/07/04 职场文书
乡镇领导干部个人对照检查材料思想汇报
2014/09/23 职场文书
《开国大典》教学反思
2016/02/16 职场文书
WordPress多语言翻译插件 - WPML使用教程
2021/04/01 PHP
Go语言切片前或中间插入项与内置copy()函数详解
2021/04/27 Golang
Python 实现定积分与二重定积分的操作
2021/05/26 Python
idea编译器vue缩进报错问题场景分析
2021/07/04 Vue.js
SQL SERVER中的流程控制语句
2022/05/25 SQL Server