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读取环境变量的方法和自定义类分享
Nov 22 Python
python爬虫入门教程--优雅的HTTP库requests(二)
May 25 Python
Python中数组,列表:冒号的灵活用法介绍(np数组,列表倒序)
Apr 18 Python
在Python中将函数作为另一个函数的参数传入并调用的方法
Jan 22 Python
Django的Modelforms用法简介
Jul 27 Python
详解在Python中使用Torchmoji将文本转换为表情符号
Jul 27 Python
Django如何在不停机的情况下创建索引
Aug 02 Python
Docker如何部署Python项目的实现详解
Oct 26 Python
python 列表推导和生成器表达式的使用
Feb 01 Python
教你怎么用Python监控愉客行车程
Apr 29 Python
关于python中readlines函数的参数hint的相关知识总结
Jun 24 Python
Python 如何利用ffmpeg 处理视频素材
Nov 27 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 discuz 主题表和回帖表的设计
2009/03/13 PHP
在WINDOWS中设置计划任务执行PHP文件的方法
2011/12/19 PHP
基于PHP遍历数组的方法汇总分析
2013/06/08 PHP
关于PHP二进制流 逐bit的低位在前算法(详解)
2013/06/13 PHP
PHP三元运算的2种写法代码实例
2014/05/12 PHP
微信access_token的获取开发示例
2015/04/16 PHP
PHP删除数组中指定下标的元素方法
2018/02/03 PHP
解决laravel查询构造器中的别名问题
2019/10/17 PHP
javascript学习笔记(十) js对象 继承
2012/06/19 Javascript
javascript强大的日期函数代码分享
2013/09/04 Javascript
parentElement,srcElement的使用小结
2014/01/13 Javascript
DOM基础教程之使用DOM + Css
2015/01/20 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
JS抛物线动画实例制作
2018/02/24 Javascript
vue实现拖拽的简单案例 不超出可视区域
2019/07/25 Javascript
jquery实现加载更多&quot;转圈圈&quot;效果(示例代码)
2020/11/09 jQuery
iview实现动态表单和自定义验证时间段重叠
2021/01/10 Javascript
[53:52]OG vs EG 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
在Python3中初学者应会的一些基本的提升效率的小技巧
2015/03/31 Python
python后端接收前端回传的文件方法
2019/01/02 Python
Python基础学习之基本数据结构详解【数字、字符串、列表、元组、集合、字典】
2019/06/18 Python
Python Tkinter模块 GUI 可视化实例
2019/11/20 Python
Django Path转换器自定义及正则代码实例
2020/05/29 Python
用python写爬虫简单吗
2020/07/28 Python
凯特王妃父母建立的派对用品网站:Party Pieces
2017/05/28 全球购物
卡骆驰英国官网:Crocs英国
2019/08/22 全球购物
社团文化节策划书
2014/02/01 职场文书
语文教学随笔感言
2014/02/18 职场文书
捐助倡议书范文
2014/04/15 职场文书
厨房领班竞聘演讲稿
2014/04/23 职场文书
中国文明网向国旗敬礼寄语大全
2014/09/27 职场文书
个人债务授权委托书范本
2014/10/05 职场文书
自我检讨书怎么写
2015/05/07 职场文书
小学英语教师研修感悟
2015/11/18 职场文书
Mybatis-Plus进阶分页与乐观锁插件及通用枚举和多数据源详解
2022/03/21 Java/Android