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 开发者节省时间的10个方法
Oct 02 Python
Python3实现发送QQ邮件功能(文本)
Dec 15 Python
NumPy 如何生成多维数组的方法
Feb 05 Python
wxPython的安装与使用教程
Aug 31 Python
对Python Class之间函数的调用关系详解
Jan 23 Python
vim自动补全插件YouCompleteMe(YCM)安装过程解析
Oct 21 Python
Python通过两个dataframe用for循环求笛卡尔积
Apr 29 Python
解决keras GAN训练是loss不发生变化,accuracy一直为0.5的问题
Jul 02 Python
Python‘==‘ 及 ‘is‘相关原理解析
Sep 05 Python
Python 用户输入和while循环的操作
May 23 Python
Python 如何解决稀疏矩阵运算
May 26 Python
Python Django ORM连表正反操作技巧
Jun 13 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边学边教》(01.开篇――准备工作)
2006/12/13 PHP
php ss7.5的数据调用 (笔记)
2010/03/08 PHP
php魔术方法功能与用法实例分析
2016/10/19 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
php微信公众号开发之图片回复
2018/10/20 PHP
laravel数据库查询结果自动转数组修改实例
2021/02/27 PHP
破解Session cookie的方法
2006/07/28 Javascript
Jquery选择器 $实现原理
2009/12/02 Javascript
js传中文参数controller里获取参数乱码问题解决方法
2014/01/03 Javascript
Javascript 数组排序详解
2014/10/22 Javascript
JavaScript 不支持 indexof 该如何解决
2016/03/30 Javascript
JS小数运算出现多为小数问题的解决方法
2016/06/02 Javascript
一个例子轻松学会Vue.js
2017/01/02 Javascript
jQuery插件zTree实现清空选中第一个节点所有子节点的方法
2017/03/08 Javascript
JavaScript实现父子dom同时绑定两个点击事件,一个用捕获,一个用冒泡时执行顺序的方法
2017/03/30 Javascript
通过vue提供的keep-alive减少对服务器的请求次数
2018/04/01 Javascript
详解JavaScript栈内存与堆内存
2019/04/04 Javascript
Vue+iview+webpack ie浏览器兼容简单处理
2019/09/20 Javascript
Python3读取UTF-8文件及统计文件行数的方法
2015/05/22 Python
Python中操作文件之write()方法的使用教程
2015/05/25 Python
python去除文件中空格、Tab及回车的方法
2016/04/12 Python
Python线程同步的实现代码
2018/10/03 Python
Python脚本按照当前日期创建多级目录
2019/03/01 Python
Python使用指定端口进行http请求的例子
2019/07/25 Python
PyCharm GUI界面开发和exe文件生成的实现
2020/03/04 Python
Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)
2020/04/08 Python
解决jupyter notebook显示不全出现框框或者乱码问题
2020/04/09 Python
python如何求100以内的素数
2020/05/27 Python
Python使用xlrd实现读取合并单元格
2020/07/09 Python
毕业生毕业总结的自我评价范文
2013/11/02 职场文书
数控专业应届生求职信
2013/11/27 职场文书
校运会入场式解说词
2014/02/10 职场文书
五好关工委申报材料
2014/05/31 职场文书
国际语言毕业生求职信
2014/07/08 职场文书
Filebeat 采集 Nginx 日志的方法
2021/03/31 Servers
浅谈克隆 JavaScript
2021/11/02 Javascript