django model object序列化实例


Posted in Python onMarch 13, 2020

提到序列化与反序列化,通常会想到 json ,xml .在J2EE的开发中,这是很常用的技术,比如一个java class与xml之间的序列化与反序列化,我们可以通过 xstream来实现,如果是与json之间的转换,我们可以通过 gson.jar或者jsonlib.jar 来实现。方法很多,也是常见的方法。

但在python 中,我们常用的是json 的序列化,python2.7 已经包含了json package,这个也是从simplejson 基础上改变而来。这个json 包主要提供了dump,load 来实现dict 与 字符串之间的序列化与反序列化,这很方便的可以完成,可以参考这篇文章python json。但现在的问题是,这个json包不能序列化 django 的models 里面的对象的实例。

经过分析,网络搜索,发现有如下解决方案.

利用 from django.core import serializers 的方法实现

from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all())
data1 = serializers.serialize("json", SomeModel.objects.filter(myfield1=myvalue))

上面两个是没有问题的,因为序列化的对象是 Queryset, 因此是成功的。但如果是用SomeModel.objects.get(id=myid) 得到一个具体的实例的时候,问题就来了

data = serializers.serialize("json", SomeModel.objects.get(id=myid))

肯定会出现如下错误:

for obj in queryset: TypeError: 'SomeModel' object is not iterable

一看错误就知道,因为 SomeModel.objects.get(id=myid) 返回的是一个具体的实例,而不是一个集合对象,因此是不可以 iterable 的。所以报错。

从上面的分析可以看出 django的 serializers 只支持 queryset,而不支持model的实例,那么怎么实现呢?

1.我们自己把这个单个对象模拟成一个集合,然后去掉前后的"[""]"符号,就可以了。

from django.utils import simplejson
from django.db import models
from django.core.serializers import serialize,deserialize
from django.db.models.query import QuerySet
from django.test import TestCase

class MyEncoder(simplejson.JSONEncoder):
   """ 继承自simplejson的编码基类,用于处理复杂类型的编码
   """
   def default(self,obj):
       if isinstance(obj,QuerySet):
         """ Queryset实例
         直接使用Django内置的序列化工具进行序列化
         但是如果直接返回serialize('json',obj)
         则在simplejson序列化时会被从当成字符串处理
         则会多出前后的双引号
         因此这里先获得序列化后的对象
         然后再用simplejson反序列化一次
         得到一个标准的字典(dict)对象
         """
         return simplejson.loads(serialize('json',obj))
       if isinstance(obj,models.Model):
         """
         如果传入的是单个对象,区别于QuerySet的就是
         Django不支持序列化单个对象
         因此,首先用单个对象来构造一个只有一个对象的数组
         这是就可以看做是QuerySet对象
         然后此时再用Django来进行序列化
         就如同处理QuerySet一样
         但是由于序列化QuerySet会被'[]'所包围
         因此使用string[1:-1]来去除
         由于序列化QuerySet而带入的'[]'
         """
         return simplejson.loads(serialize('json',[obj])[1:-1])
       if hasattr(obj, 'isoformat'):
         #处理日期类型
         return obj.isoformat()
       return simplejson.JSONEncoder.default(self,obj)

def jsonBack(json):
   """  进行Json字符串的反序列化
     一般来说,从网络得回的POST(或者GET)
     参数中所包含json数据
     例如,用POST传过来的参数中有一个key value键值对为
     request.POST['update']
     = "[{pk:1,name:'changename'},{pk:2,name:'changename2'}]"
     要将这个value进行反序列化
     则可以使用Django内置的序列化与反序列化
     但是问题在于
     传回的有可能是代表单个对象的json字符串
     如:
     request.POST['update'] = "{pk:1,name:'changename'}"
     这是,由于Django无法处理单个对象
     因此要做适当的处理
     将其模拟成一个数组,也就是用'[]'进行包围
     再进行反序列化
   """
   if json[0] == '[':
     return deserialize('json',json)
   else:
     return deserialize('json','[' + json +']')

def getJson(**args):
   """  使用MyEncoder这个自定义的规则类来序列化对象
   """
   result = dict(args)
   return simplejson.dumps(result,cls=MyEncoder)

在上面的例子中,自定义了一个序列化规则类MyEncoder,用来处理集合或者集合对象,然后实现了一个可变参数的工具方法getJson,用于传入多个参数,并将其一同序列化。另外还有一个反序列化对象的方法jsonBack,接受一个代表对象或者对象集合的json而返回一个对象集合。这样一来就可以很好的使用配合SimpleJson和Django来完成序列化工作了

2.直接利用python 2.7 提供的json包,或者用simplejson都可以

首先,你需要在django model的定义中增加一个方法toJSON,利用了django model 能访问 _meta.fields 得到相关属性而得到,例子如下

class Category(models.Model):
  autoid = models.AutoField(primary_key=True)
  email=models.CharField(max_length=150,blank=False)
  comtype=models.CharField(max_length=20,blank=False)
  catname=models.CharField(max_length=150,blank=False) 
  
  def __unicode__(self):
    return '%s' % (self.catname)
  
  def toJSON(self):
    import json
    return json.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

现在用django查出数据,并转换成json

row=models.Category.objects.get(autoid=23) print row.toJSON()

你会发现,成功转换了。当然,这个toJSON方法,如果要求可读性比较好的话,可以这样写

def toJSON(self):
  fields = []
  for field in self._meta.fields:
    fields.append(field.name)

  d = {}
  for attr in fields:
    d[attr] = getattr(self, attr)

  import json
  return json.dumps(d)

补充知识:django模型类序列化器 ModelSerializer

1. 定义

比如我们创建一个BookInfoSerializer

class BookInfoSerializer(serializers.ModelSerializer):
  """图书数据序列化器"""
  class Meta:
    model = BookInfo
    fields = '__all__'

model 指明参照哪个模型类

fields 指明为模型类的哪些字段生成

2. 指定字段

1) 使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如

class BookInfoSerializer(serializers.ModelSerializer):
  """图书数据序列化器"""
  class Meta:
    model = BookInfo
    fields = ('id', 'btitle', 'bpub_date')

2) 使用exclude可以明确排除掉哪些字段

class BookInfoSerializer(serializers.ModelSerializer):
  """图书数据序列化器"""
  class Meta:
    model = BookInfo
    exclude = ('image',)

3) 默认ModelSerializer使用主键作为关联字段,但是我们可以使用depth来简单的生成嵌套表示,depth应该是整数,表明嵌套的层级数量。如:

class HeroInfoSerializer2(serializers.ModelSerializer):
  class Meta:
    model = HeroInfo
    fields = '__all__'
    depth = 1

4) 指明只读字段

可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段

3. 添加额外参数

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

class BookInfoSerializer(serializers.ModelSerializer):
  """图书数据序列化器"""
  class Meta:
    model = BookInfo
    fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
    extra_kwargs = {
      'bread': {'min_value': 0, 'required': True},
      'bcomment': {'min_value': 0, 'required': True},
    }

以上这篇django model object序列化实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python BeautifulSoup中文乱码问题的2种解决方法
Apr 22 Python
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
Jun 09 Python
python中的装饰器详解
Apr 13 Python
在Windows服务器下用Apache和mod_wsgi配置Python应用的教程
May 06 Python
Python面向对象编程中关于类和方法的学习笔记
Jun 30 Python
详解Python异常处理中的Finally else的功能
Dec 29 Python
python通过ffmgep从视频中抽帧的方法
Dec 05 Python
使用Python开发SQLite代理服务器的方法
Dec 07 Python
10 行Python 代码实现 AI 目标检测技术【推荐】
Jun 14 Python
Django命名URL和反向解析URL实现解析
Aug 09 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
Nov 25 Python
Python实现井字棋小游戏
Mar 09 Python
浅析python标准库中的glob
Mar 13 #Python
Python3标准库glob文件名模式匹配的问题
Mar 13 #Python
python编写俄罗斯方块
Mar 13 #Python
探秘TensorFlow 和 NumPy 的 Broadcasting 机制
Mar 13 #Python
自定义Django Form中choicefield下拉菜单选取数据库内容实例
Mar 13 #Python
django处理select下拉表单实例(从model到前端到post到form)
Mar 13 #Python
python实现俄罗斯方块游戏(改进版)
Mar 13 #Python
You might like
十天学会php(1)
2006/10/09 PHP
php,不用COM,生成excel文件
2006/10/09 PHP
xajax写的留言本
2006/11/25 PHP
实现了一个PHP5的getter/setter基类的代码
2007/02/25 PHP
mysql 字段类型说明
2007/04/27 PHP
PHP 抽象方法与抽象类abstract关键字介绍及应用
2014/10/16 PHP
PHP安全下载文件的方法
2016/04/07 PHP
thinkphp Apache配置重启Apache1 restart 出错解决办法
2017/02/15 PHP
使用PHPExcel导出Excel表
2018/09/08 PHP
JavaScript 创建对象和构造类实现代码
2009/07/30 Javascript
jQuery 动态酷效果实现总结
2009/12/27 Javascript
js、jquery图片动画、动态切换示例代码
2014/06/03 Javascript
jQuery实现渐变弹出层和弹出菜单的方法
2015/02/20 Javascript
详细解读JavaScript的跨浏览器事件处理
2015/08/12 Javascript
js仿支付宝填写支付密码效果实现多方框输入密码
2016/03/09 Javascript
总结javascript中的六种迭代器
2016/08/16 Javascript
javascript闭包功能与用法实例分析
2017/04/06 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
2018/05/01 Javascript
vue.js轮播图组件使用方法详解
2018/07/03 Javascript
JavaScript实现栈结构Stack过程详解
2020/03/07 Javascript
python使用os模块的os.walk遍历文件夹示例
2014/01/27 Python
python通过urllib2爬网页上种子下载示例
2014/02/24 Python
Python格式化css文件的方法
2015/03/10 Python
Python的Django框架下管理站点的基本方法
2015/07/17 Python
Django 前后台的数据传递的方法
2017/08/08 Python
python批量复制图片到另一个文件夹
2018/09/17 Python
Python lxml解析HTML并用xpath获取元素的方法
2019/01/02 Python
浅谈tensorflow之内存暴涨问题
2020/02/05 Python
解决pyinstaller打包运行程序时出现缺少plotly库问题
2020/06/02 Python
Python连接Impala实现步骤解析
2020/08/04 Python
如何用 Python 制作 GitHub 消息助手
2021/02/20 Python
家庭户外服装:Hawkshead
2017/11/02 全球购物
美国时尚配饰品牌:Dooney & Bourke
2017/11/14 全球购物
澳大利亚领先的在线药房:Pharmacy Online(有中文站)
2020/02/22 全球购物
寻找迷宫的一条出路,o通路;X:障碍
2016/07/10 面试题
办公室文员工作自我评价
2013/12/01 职场文书