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爬取网站数据保存使用的方法
Nov 20 Python
Python变量和字符串详解
Apr 29 Python
python、java等哪一门编程语言适合人工智能?
Nov 13 Python
使用python爬取B站千万级数据
Jun 08 Python
Python登录注册验证功能实现
Jun 18 Python
IntelliJ IDEA安装运行python插件方法
Dec 10 Python
树莓派实现移动拍照
Jun 22 Python
使用python 写一个静态服务(实战)
Jun 28 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
Jul 04 Python
Python类中的魔法方法之 __slots__原理解析
Aug 26 Python
QML使用Python的函数过程解析
Sep 26 Python
Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)
Dec 07 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 cout<<的一点看法
2010/01/24 PHP
php使HTML标签自动补全闭合函数代码
2012/10/04 PHP
PHP编程基本语法快速入门手册
2016/01/07 PHP
建议大家看下JavaScript重要知识更新
2007/07/08 Javascript
用javascript做拖动布局的思路
2008/05/31 Javascript
javascript 按回车键相应按钮提交事件
2009/11/02 Javascript
ExtJS 入门
2010/10/29 Javascript
JS的document.all函数使用示例
2013/12/30 Javascript
javascript引擎长时间独占线程造成卡顿的解决方案
2014/12/03 Javascript
javascript 获取浏览器版本
2015/01/21 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
2015/10/29 Javascript
jQuery+ajax实现实用的点赞插件代码
2016/07/06 Javascript
微信小程序学习笔记之函数定义、页面渲染图文详解
2019/03/28 Javascript
javascript function(函数类型)使用与注意事项小结
2019/06/10 Javascript
Vue使用Three.js加载glTF模型的方法详解
2020/06/14 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
django模型中的字段和model名显示为中文小技巧分享
2014/11/18 Python
分析Python的Django框架的运行方式及处理流程
2015/04/08 Python
使用python实现rsa算法代码
2016/02/17 Python
浅谈Python黑帽子取代netcat
2018/02/10 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
2018/06/09 Python
对python数据切割归并算法的实例讲解
2018/12/12 Python
Python逐行读取文件中内容的简单方法
2019/02/26 Python
python实现维吉尼亚加密法
2019/03/20 Python
使用Python爬取小姐姐图片(beautifulsoup法)
2021/02/11 Python
如何让IE9以下版本(ie6/7/8)认识html5元素
2013/04/01 HTML / CSS
美国在线乐器和设备商店:Musician’s Friend
2018/07/06 全球购物
澳大利亚电商Catch新西兰站:Catch.co.nz
2020/05/30 全球购物
2013年大学生的自我鉴定
2013/10/24 职场文书
应届生保险求职信
2013/11/11 职场文书
《生命的药方》教学反思
2014/04/08 职场文书
秋天的雨教学反思
2014/04/27 职场文书
再婚婚前财产协议书范本
2014/10/19 职场文书
小学班主任评语
2014/12/29 职场文书
个人创业事迹材料
2014/12/30 职场文书
Redis主从配置和底层实现原理解析(实战记录)
2021/06/30 Redis