Serialize----序列化django对象
django的序列化框架提供了一个把django对象转换成其他格式的机制,通常这些其他的格式都是基于文本的并且用于通过一个管道发送django对象,但一个序列器是可能处理任何一个格式的(基于文本或者不是)
django的序列化类位于django.core下面的serializers文件夹里面,base.py文件里面定义了序列器和反序列器的基类以及一些异常,__init__.py文件定义了如何根据格式来选择对应的序列器等内容,我们一起来看看吧
__init__.py和base.py文件的函数原型如下图
def serialize(format, queryset, **options): |
|
class Serializer(object): |
那下面我们开始正式讲解django的序列化操作了
序列化数据
在最高层的api,序列化数据是非常容易的操作,看上面的函数可知,serialize函数接受一个格式和queryset,返回序列化后的数据:
简单的写法:
from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())
复杂的写法:
XMLSerializer = serializers.get_serializer("xml")
xml_serializer = XMLSerializer()
xml_serializer.serialize(queryset)
data = xml_serializer.getvalue()
解序列化数据
一样的简单,接受一个格式和一个数据流,返回一个迭代器
for obj in serializers.deserialize("xml", data):
do_something_with(obj)
然而,deserialize返回的的是不是简单的django类型对象,而是DeserializedObject实例,并且这些实例是没有保存的,请使用DeserializedObject.save()方法把这些数据保存到数据库
序列化格式
django之处很多的序列化格式,有些需要你安装第三方支持的模块,xml,json和yaml是默认支持的
注意事项
如果你是使用utf-8或者其他的非ascii编码数据,然后用json序列器,注意穿一个ensure_ascii参数进去,否则输出的编码将会不正常
json_serializer = serializers.get_serializer("json")()
json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
序列化参数
序列化的是是可以接受额外的参数的,总共有三个参数,如下:
self.stream = options.pop("stream", StringIO())
self.selected_fields = options.pop("fields", None)
self.use_natural_keys = options.pop("use_natural_keys", False)
stream
将序列化后的数据输出到该stream流中,接上面的复杂的写法:
out = open("file.xml", "w")
xml_serializer.serialize(SomeModel.objects.all(), stream=out)
selected_field
选择序列化的属性,通过制定fields参数,fields是一个元组参数,元素是选择要序列化的属性
from django.core import serializers
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
use_natural_keys
是否使用自然的关键字,默认是false(即是使用主键)
默认的外键和多对多关系序列化策略是使用主键,一般情况下是很好地,但有些情况下就不是这样了。比如外键到ContentType的时候,由于ContentType是django的数据库进程同步的时候自动产生的,它们的关键字不是那么容易去预测的。
一个整数id也不总是最方便的索引到一个对象的方法,所以基于这些情况,django提供了use_natural_keys这个参数,
一个natural key是一个可以不使用主键就可以用来区分一个元素的属性组合的元组
natural keys的解序列化
考虑这两个模型
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
birthdate = models.DateField()
class Meta:
unique_together = (('first_name', 'last_name'),)
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Person)
默认Book 的序列化数据将会使用一个整数索引到一个作者,例如,用json的是,一个Book的序列化数据大概是这样的,42是外键Author的主键
{
"pk": 1,
"model": "store.book",
"fields": {
"name": "Mostly Harmless",
"author": 42
}
}
但这不是一个很好的方法,不是吗?你需要知道这个主键代表到底是哪个Author,并且要求这个主键是稳定和可预测的。所以,我们可以增加一个natural key的处理函数,请在对应模型的管理模型里面定义一个get_by_natural_key方法,例如:
from django.db import models
class PersonManager(models.Manager):
def get_by_natural_key(self, first_name, last_name):
return self.get(first_name=first_name, last_name=last_name)
class Person(models.Model):
objects = PersonManager()
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
birthdate = models.DateField()
class Meta:
unique_together = (('first_name', 'last_name'),)
这样之后,序列化的结果大概是这样的:
{
"pk": 1,
"model": "store.book",
"fields": {
"name": "Mostly Harmless",
"author": ["Douglas", "Adams"]
}
}
natural keys的序列化
如果你想在序列化的时候使用natural key,那你必须在被序列化的模型里面顶一个natural_key方法,并在序列化的时候使用use_natural_keys=True属性如下:
class Person(models.Model):
objects = PersonManager()
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
birthdate = models.DateField()
def natural_key(self):
return (self.first_name, self.last_name)
class Meta:
unique_together = (('first_name', 'last_name'),)
serializers.serialize('json', [book1, book2], use_natural_keys=True)
注意:natural_key()和get_by_natural_key()不是同时定义的,如果你只想重载natural keys的能力,那么你不必定义natural_key()方法;同样,如果你只想在序列化的时候输出这些natural keys,那么你不必定义get_by_natural_key()方法
序列化过程中的依赖关系
因为natural keys依赖数据库查询来解析引用,所以在数据被引用之前必须确保数据是存在的。看下面的例子,如果一个Book的natural key是书名和作者的组合,你可以这样写:
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Person) def natural_key(self):
return (self.name,) + self.author.natural_key()
那么问题来了,如果Author还没有被序列化呢?很明显,Author应该在Book之前被序列化,为此,我们可以添加一个依赖关系如下:
def natural_key(self):
return (self.name,) + self.author.natural_key()
natural_key.dependencies = ['example_app.person']
这保证了Person对象是在Book对象之前被序列化的,同样,任何一个引用Book的对象只有在Person和Book对象都被序列化之后才会被序列化
继承的模型
如果是使用抽象继承的时候,不必在意这个问题;如果你使用的是多表继承,那么注意了:必须序列化所有的基类,例如:
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField()
如果仅仅序列化Restaurant模型,那么只会得到一个serves_hot_dog属性,基类的属性将被忽略,你必须同时序列化所有的继承的模型,如下:
all_objects = list(Restaurant.objects.all()) + list(Place.objects.all())
data = serializers.serialize('xml', all_objects)
Serialize----序列化django对象的更多相关文章
- 21:序列化django对象
django的序列化框架提供了一个把django对象转换成其他格式的机制,通常这些其他的格式都是基于文本的并且用于通过一个管道发送django对象,但一个序列器是可能处理任何一个格式的(基于文本或者不 ...
- (转)jquery serialize表单序列化,当radio或checkbox 未选中时,没有序列化到对象中的原因分析和解决方案 - ghostsf
相信很多人都用过jq的表单序列化serialize()方法,因为这能很方便地帮你把表单里所有的非禁用输入控件序列化为 key/value 对象,不需要你再去一个个地拼接参数了. 这是一个很好用的函数, ...
- 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用
写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...
- php serialize序列化对象或者数组
serialize序列化对象或者数组 $str=serialize(array('a'=>1,'b'=>2)); echo $str; 输入出a:2:{s:1:"a"; ...
- JSON格式化与serialize序列化
一.JSON格式化 1. JSON是什么 JSON是一种数据的存储格式,用来沟通客户端Javascript和服务端PHP的交互.我们把用PHP生成JSON后的字符串传给前台Javascript,Jav ...
- .NET调用外部接口将得到的List数据,并使用XmlSerializer序列化List对象成XML格式
BidOpeningData.BidSupervisionSoapClient client = new BidOpeningData.BidSupervisionSoapClient(); Dict ...
- JQuery中serialize() 序列化
更多2014/8/24 来源:jquery学习浏览量:1671 学习标签: serialize 本文导读:在jQuery中,当我们使用ajax时,常常需要拼装input数据以键值对(Key/Value ...
- redis 序列化存入对象
redis 序列化存入对象 //序列化 public static byte [] serialize(Object obj){ ObjectOutputStream obi=null; ByteAr ...
- Atitit php序列化 php的serialize序列化和json序列化
Atitit php序列化 php的serialize序列化和json序列化 PHP 对不同类型的数据用不同的字母进行标示,Yahoo 开发网站提供的Using Serialized PHP with ...
随机推荐
- C语言初学者代码中的常见错误与瑕疵(4)
问题 小学生数学 很多小学生在学习加法时,发现“进位”特别容易出错.你的任务是计算两个数在相加时需要多少次进位.你编制的程序应当可以连续处理多组数据,直到读到两个0(这是输入结束标记). 样例: 输入 ...
- 使用Application Loader打包上传AppStore流程
配置完你的证书,Bundle Identifier 和描述文件的配置 然后配置工程打开你项目工程 第一步,这里不能选择模拟器,选择iOS Device 如果不支持横屏,把这2个勾去掉 然后查看版本号和 ...
- JProfiler入门笔记
看链接:http://blog.csdn.net/chendc201/article/details/22897999 收集一下.
- STM32的PWM输出极性的问题
又开始玩PWM, 先试了一下PWM的两个引脚输出相反极性, 但是分析仪上看到, 两个脚是一样一样的. 写是这么写的: ... TIM_OCInitStructure.TIM_OCMode=TIM_OC ...
- matlab读入矩阵数据
方法: 很简单,把矩阵数据存到excel里,然后存成cvs的格式,就是把每行数据之间用‘,’分隔:行与行之间用‘\n’保存. 举例: 假设cvs为test_nnfeature.txt,后缀可以改啦,只 ...
- Redis整合Spring结合使用缓存实例
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文介绍了如何在Spring中配置redis,并通过Spring中AOP的思想,将缓存的 ...
- JavaEE基础(八)
1.面向对象(代码块的概述和分类)(了解)(面试的时候会问,开发不用或者很少用) A:代码块概述 在Java中,使用{}括起来的代码被称为代码块. B:代码块分类 根据其位置和声明的不同,可以分为局部 ...
- 编译器 perforSelecter时 警告去除
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks&quo ...
- 删除 SQL Server 2005 Express 工具
安装sql server 2008 management,提示错误:Sql2005SsmsExpressFacet 检查是否安装了 SQL Server 2005 Express 工具. 失败,已安装 ...
- discuz x2 diy 模块的样式点击不管用,模块的数据、标题都可以编辑
这个是diy模板的文件忘记添加 <style id="diy_style" type="text/css"></style> 一 ...