django model object序列化实例
提到序列化与反序列化,通常会想到json,xml.在J2EE的开发中,这是很常用的技术,比如一个javaclass与xml之间的序列化与反序列化,我们可以通过xstream来实现,如果是与json之间的转换,我们可以通过gson.jar或者jsonlib.jar来实现。方法很多,也是常见的方法。
但在python中,我们常用的是json的序列化,python2.7已经包含了jsonpackage,这个也是从simplejson基础上改变而来。这个json包主要提供了dump,load来实现dict与字符串之间的序列化与反序列化,这很方便的可以完成,可以参考这篇文章pythonjson。但现在的问题是,这个json包不能序列化django的models里面的对象的实例。
经过分析,网络搜索,发现有如下解决方案.
利用fromdjango.coreimportserializers的方法实现
fromdjango.coreimportserializers 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))
肯定会出现如下错误:
forobjinqueryset:TypeError:'SomeModel'objectisnotiterable
一看错误就知道,因为SomeModel.objects.get(id=myid)返回的是一个具体的实例,而不是一个集合对象,因此是不可以iterable的。所以报错。
从上面的分析可以看出django的serializers只支持queryset,而不支持model的实例,那么怎么实现呢?
1.我们自己把这个单个对象模拟成一个集合,然后去掉前后的"[""]"符号,就可以了。
fromdjango.utilsimportsimplejson fromdjango.dbimportmodels fromdjango.core.serializersimportserialize,deserialize fromdjango.db.models.queryimportQuerySet fromdjango.testimportTestCase classMyEncoder(simplejson.JSONEncoder): """继承自simplejson的编码基类,用于处理复杂类型的编码 """ defdefault(self,obj): ifisinstance(obj,QuerySet): """Queryset实例 直接使用Django内置的序列化工具进行序列化 但是如果直接返回serialize('json',obj) 则在simplejson序列化时会被从当成字符串处理 则会多出前后的双引号 因此这里先获得序列化后的对象 然后再用simplejson反序列化一次 得到一个标准的字典(dict)对象 """ returnsimplejson.loads(serialize('json',obj)) ifisinstance(obj,models.Model): """ 如果传入的是单个对象,区别于QuerySet的就是 Django不支持序列化单个对象 因此,首先用单个对象来构造一个只有一个对象的数组 这是就可以看做是QuerySet对象 然后此时再用Django来进行序列化 就如同处理QuerySet一样 但是由于序列化QuerySet会被'[]'所包围 因此使用string[1:-1]来去除 由于序列化QuerySet而带入的'[]' """ returnsimplejson.loads(serialize('json',[obj])[1:-1]) ifhasattr(obj,'isoformat'): #处理日期类型 returnobj.isoformat() returnsimplejson.JSONEncoder.default(self,obj) defjsonBack(json): """进行Json字符串的反序列化 一般来说,从网络得回的POST(或者GET) 参数中所包含json数据 例如,用POST传过来的参数中有一个keyvalue键值对为 request.POST['update'] ="[{pk:1,name:'changename'},{pk:2,name:'changename2'}]" 要将这个value进行反序列化 则可以使用Django内置的序列化与反序列化 但是问题在于 传回的有可能是代表单个对象的json字符串 如: request.POST['update']="{pk:1,name:'changename'}" 这是,由于Django无法处理单个对象 因此要做适当的处理 将其模拟成一个数组,也就是用'[]'进行包围 再进行反序列化 """ ifjson[0]=='[': returndeserialize('json',json) else: returndeserialize('json','['+json+']') defgetJson(**args): """使用MyEncoder这个自定义的规则类来序列化对象 """ result=dict(args) returnsimplejson.dumps(result,cls=MyEncoder)
在上面的例子中,自定义了一个序列化规则类MyEncoder,用来处理集合或者集合对象,然后实现了一个可变参数的工具方法getJson,用于传入多个参数,并将其一同序列化。另外还有一个反序列化对象的方法jsonBack,接受一个代表对象或者对象集合的json而返回一个对象集合。这样一来就可以很好的使用配合SimpleJson和Django来完成序列化工作了
2.直接利用python2.7提供的json包,或者用simplejson都可以
首先,你需要在djangomodel的定义中增加一个方法toJSON,利用了djangomodel能访问_meta.fields得到相关属性而得到,例子如下
classCategory(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) deftoJSON(self): importjson returnjson.dumps(dict([(attr,getattr(self,attr))forattrin[f.nameforfinself._meta.fields]]))
现在用django查出数据,并转换成json
row=models.Category.objects.get(autoid=23)printrow.toJSON()
你会发现,成功转换了。当然,这个toJSON方法,如果要求可读性比较好的话,可以这样写
deftoJSON(self): fields=[] forfieldinself._meta.fields: fields.append(field.name) d={} forattrinfields: d[attr]=getattr(self,attr) importjson returnjson.dumps(d)
补充知识:django模型类序列化器ModelSerializer
1.定义
比如我们创建一个BookInfoSerializer
classBookInfoSerializer(serializers.ModelSerializer): """图书数据序列化器""" classMeta: model=BookInfo fields='__all__'
model指明参照哪个模型类
fields指明为模型类的哪些字段生成
2.指定字段
1)使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如
classBookInfoSerializer(serializers.ModelSerializer): """图书数据序列化器""" classMeta: model=BookInfo fields=('id','btitle','bpub_date')
2)使用exclude可以明确排除掉哪些字段
classBookInfoSerializer(serializers.ModelSerializer): """图书数据序列化器""" classMeta: model=BookInfo exclude=('image',)
3)默认ModelSerializer使用主键作为关联字段,但是我们可以使用depth来简单的生成嵌套表示,depth应该是整数,表明嵌套的层级数量。如:
classHeroInfoSerializer2(serializers.ModelSerializer): classMeta: model=HeroInfo fields='__all__' depth=1
4)指明只读字段
可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段
3.添加额外参数
我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
classBookInfoSerializer(serializers.ModelSerializer): """图书数据序列化器""" classMeta: model=BookInfo fields=('id','btitle','bpub_date','bread','bcomment') extra_kwargs={ 'bread':{'min_value':0,'required':True}, 'bcomment':{'min_value':0,'required':True}, }
以上这篇djangomodelobject序列化实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。