Django框架序列化与反序列化操作详解


Posted in Python onNovember 01, 2019

本文实例讲述了Django框架序列化与反序列化操作。分享给大家供大家参考,具体如下:

Serializer类

1.定义:

Django REST framework中的Serializer使用类来定义,须继承rest_framework.serializers.Serializer。

例:

class BookInfoSerializer(serializers.Serializer):
 """图书数据序列化器"""
 id = serializers.IntegerField(label='ID', read_only=True)
 name = serializers.CharField(label='名称', max_length=20)
 pub_date = serializers.DateField(label='发布日期', required=False)
 readcount = serializers.IntegerField(label='阅读量', required=False)
 commentcount = serializers.IntegerField(label='评论量', required=False)
 image = serializers.ImageField(label='图片', required=False)

2.字段与选项:

常用字段类型:

字段 字段构造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format=‘hex_verbose') format: 1)
IPAddressField IPAddressField(protocol=‘both', unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices与Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

选项参数:

参数名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最大值
min_value 最小值

通用参数:

参数名称 说明
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息

3.Serialize对象:

构造方法:

Serializer(instance, data, **kwarg)

(1)用于序列化时,将模型类对象传入instance参数
(2)用于反序列化时,将要被反序列化的数据传入data参数
(3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外 添加数据。

例:

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

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

序列化

1.基本使用:

(1)查询对象:
例:

from book.models import BookInfo
book = BookInfo.objects.get(id=4) # 单个对象
books = BookInfo.objects.all() # 多个对象

(2)构造序列化对象:

from book.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book) # 单个对象
serializers = BookInfoSerializer(books,many=True) # 多个对象需要添加many参数

(3)获取序列化数据:

serializer.data

2.外键嵌套使用:

(1)PrimaryKeyRelatedField:

此字段将被序列化为关联对象的主键。

book = serializers.PrimaryKeyRelatedField(label='图书',read_only=True)

或者

book=serializers.PrimaryKeyRelatedField(label='图书',queryset=BookInfo.objects.all())

指明字段时需要包含read_only=True或者queryset参数:

  • 包含read_only=True参数时,该字段将不能用作反序列化使用
  • 包含queryset参数时,将被用作反序列化时参数校验使用

结果:

{'id': 10, 'book': 3, 'description': '独孤九剑', 'gender': 1, 'name': '令狐冲'}

(2)StringRelateField:

此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)

book = serializers.StringRelatedField(label='图书')

结果:

{'description': '独孤九剑', 'name': '令狐冲', 'gender': 1, 'book': '笑傲江湖', 'id': 10}

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

book = BookInfoSerializer()

结果:

{'book': OrderedDict([('id', 3), ('name', '笑傲江湖'), ('pub_date', '1995-12-24'),  ('readcount', 28), ('commentcount',  ('image', None)]), 'gender': 1, 'name': '令狐冲',  'description': '独孤九剑', 'id': 10}

反序列化

1.验证:

(1)字段验证:

from book.serializers import BookInfoSerializer
data = {'pub_date':'2010-1-1','name':'python高级'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # 验证成功返回True,失败返回False

is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

(2)字段选项:

可在序列化器中设置字段的属性,来限制数据,对数据进行验证。

例:

属性 描述
max_length 字符串的最大长度(char)
min_length 字符串的最小长度
max_value 最大值(int)
min_value 最小值
required 表明该字段在反序列化时必须输入,默认True
default 默认值

(3)单个字段验证:

当我们的类型和选项都满足条件之后,我们需要对单个字段的值进行校验,我们在序 列化器中实现方法以 validate_ 开头以字段名结尾的函数

格式:

def validate_字段名(self,value):
...
return value

例:

def validate_readcount(self,value):
  if value < 0:
   raise serializers.ValidationError('阅读量不能为负数')
  # 验证完成之后,需要将 value返回
  return value

(4)多的字段验证:

对多个字段进行校验的时候,我们在序列器中实现

格式:

def validate(self,attrs)
...
  return attrs

例:

def validate(self, data):
  # attrs = data
  # params --> 序列化器data --> attrs
  """
  data = {
   'name':'python',
   'pub_date':'2000-1-1',
   'readcount':10,
   'commentcount':100
  }
  """
  readcount = data.get('readcount')
  # if readcount<0:
  #  raise serializers.ValidationError()
  commentcount = data.get('commentcount')
  if readcount<commentcount:
   raise serializers.ValidationError('评论量不能大于阅读量')
  #校验完成之后,必须要将数据返回回去
  return data

(5)自定义验证:

在字段中添加validators选项参数,也可以补充验证行为

例:

name=serializers.CharField(max_length=20,validators=[custom_validate)]
def custom_validate(self):
if self == 'admin':
raise serializers.ValidationError('admin不可用')
 raise serializers.ValidationError('我就是来捣乱的')

2.保存:

如果在验证成功后,想要基于validated_data完成数据对象的创建,可以通过实现create()和update()两个方法来实现。

(1)create方法:

def create(self, validated_data):
  # validated_data 验证之后的数据
  # params(前端提交的数据) --> data(序列器接受的数据) --> attrs(多个字段 校验) --> validated_data(校验之后)
  # 如果前段提交的数据 经过序列化器的验证之后完全满足需求,则
  # validated_data = params
  """
   validated_data:
  data = {
   'name':'python',
   'pub_date':'2000-1-1',
   'readcount':10000,
   'commentcount':100
  }
  """
  # book = BookInfo()
  # book.save()
  book = BookInfo.objects.create(**validated_data)
  # 需要将创建的对象返回
  return book
( return BookInfo.objects.create(**validated_data)也可)

(2)update方法:

def update(self, instance, validated_data):
"""更新,instance为要更新的对象实例"""
 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.save()
 return instance

实现了上述两个方法后,在反序列化数据的时候,就可以通过save()方法返回一个数据对象实例了

例:

book = serializer.save()

如果创建序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,则调用save()方法的时候,update()被调用。

两点说明:

1) 在对序列化器进行save()保存时,可以额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到

serializer.save(owner=request.user)

2)默认序列化器必须传递所有required的字段,否则会抛出验证异常。但是我们可以使用partial参数来允许部分字段更新

serializer = BookInfoSerializer(instance=book, data={'pub_date': '2999-1-1'}, partial=True)

模型类序列化器BookModelSerializer

1.定义:

例:

创建一个BookInfoSerializer

class BookInfoSerializer(serializers.ModelSerializer):

 class Meta:
  model = BookInfo
  fields = '__all__'

参数 描述
model 指明参照哪个模型类
fields 指明为模型类的哪些字段生成

2.指定字段:

(1)全部字段:

fields = '__all__'

(2)排除字段:

exclude = ['xxx', 'xxxx'...]

(3)指定字段:

fields = ['xxx', 'xxxx'...]

(4)只读字段:

read_only_fields = ['xxx', 'xxxx'...]

3.添加额外参数:

可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数

例:

class BookInfoSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
 fields = ('id','name', 'readcount', 'commentcount')
 read_only_fields = ('id', 'readcount', 'commentcount')
 extra_kwargs = {
  'readcount': {'min_value': 0, 'required': True},
  'commentcount': {'max_value': 0, 'required': True},
 }

希望本文所述对大家基于Django框架的Python程序设计有所帮助。

Python 相关文章推荐
Python的Flask框架中实现分页功能的教程
Apr 20 Python
实例讲解Python设计模式编程之工厂方法模式的使用
Mar 02 Python
Python中asyncore异步模块的用法及实现httpclient的实例
Jun 28 Python
举例讲解Python的lambda语句声明匿名函数的用法
Jul 01 Python
python查看微信好友是否删除自己
Dec 19 Python
Django 路由系统URLconf的使用
Oct 11 Python
Python闭包和装饰器用法实例详解
May 22 Python
基于django ManyToMany 使用的注意事项详解
Aug 09 Python
tensorflow实现对张量数据的切片操作方式
Jan 19 Python
tensorflow保持每次训练结果一致的简单实现
Feb 17 Python
pycharm实现print输出保存到txt文件
Jun 01 Python
解决python和pycharm安装gmpy2 出现ERROR的问题
Aug 28 Python
redis数据库及与python交互用法简单示例
Nov 01 #Python
python验证码图片处理(二值化)
Nov 01 #Python
使用matlab或python将txt文件转为excel表格
Nov 01 #Python
python 图片二值化处理(处理后为纯黑白的图片)
Nov 01 #Python
Python网络编程之使用TCP方式传输文件操作示例
Nov 01 #Python
wxpython布局的实现方法
Nov 01 #Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
Nov 01 #Python
You might like
php检查字符串中是否包含7位GSM字符的方法
2015/03/17 PHP
Yii的Srbac插件用法详解
2016/07/14 PHP
php编程实现简单的网页版计算器功能示例
2017/04/26 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
PHP实现链式操作的三种方法详解
2017/11/16 PHP
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
JavaScript Event学习第五章 高级事件注册模型
2010/02/07 Javascript
js switch case default 的用法示例介绍
2013/10/23 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
JavaScript实现的简单幂函数实例
2015/04/17 Javascript
JS获取CSS样式(style/getComputedStyle/currentStyle)
2016/01/19 Javascript
JS中对象与字符串的互相转换详解
2016/05/20 Javascript
微信小程序-消息提示框实例
2016/11/24 Javascript
详解利用jsx写vue组件的方法示例
2017/07/17 Javascript
JS实现动态生成html table表格的方法分析
2018/07/11 Javascript
基于vue2.0的活动倒计时组件countdown(附源码下载)
2018/10/09 Javascript
ES6 Object属性新的写法实例小结
2019/06/25 Javascript
js实现自定义右键菜单
2020/05/18 Javascript
uniapp,微信小程序中使用 MQTT的问题
2020/07/11 Javascript
Python和perl实现批量对目录下电子书文件重命名的代码分享
2014/11/21 Python
python数据持久存储 pickle模块的基本使用方法解析
2019/08/30 Python
pytorch标签转onehot形式实例
2020/01/02 Python
使用Python实现牛顿法求极值
2020/02/10 Python
使用Keras加载含有自定义层或函数的模型操作
2020/06/10 Python
python中元组的用法整理
2020/06/15 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
Pycharm无法打开双击没反应的问题及解决方案
2020/08/17 Python
HTML5新增的Css选择器、伪类介绍
2013/08/07 HTML / CSS
Crucial英睿达法国官网:内存条及SSD固态硬盘升级
2018/07/13 全球购物
自1926年以来就为冰岛保持温暖:66°North
2020/11/27 全球购物
计算机应用专业推荐信
2013/11/13 职场文书
创建青年文明号材料
2014/05/09 职场文书
国际商贸专业自荐信
2014/06/09 职场文书
财务科长个人对照检查材料
2014/09/18 职场文书
公司人事管理制度
2015/08/05 职场文书