django model object序列化實例
提到序列化與反序列化,通常會想到 json ,xml .在J2EE的開發(fā)中,這是很常用的技術,比如一個java class與xml之間的序列化與反序列化,我們可以通過 xstream來實現(xiàn),如果是與json之間的轉換,我們可以通過 gson.jar或者jsonlib.jar 來實現(xiàn)。方法很多,也是常見的方法。
但在python 中,我們常用的是json 的序列化,python2.7 已經包含了json package,這個也是從simplejson 基礎上改變而來。這個json 包主要提供了dump,load 來實現(xiàn)dict 與 字符串之間的序列化與反序列化,這很方便的可以完成,可以參考這篇文章python json。但現(xiàn)在的問題是,這個json包不能序列化 django 的models 里面的對象的實例。
經過分析,網絡搜索,發(fā)現(xiàn)有如下解決方案.
利用 from django.core import serializers 的方法實現(xiàn)
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))
肯定會出現(xiàn)如下錯誤:
for obj in queryset: TypeError: 'SomeModel' object is not iterable
一看錯誤就知道,因為 SomeModel.objects.get(id=myid) 返回的是一個具體的實例,而不是一個集合對象,因此是不可以 iterable 的。所以報錯。
從上面的分析可以看出 django的 serializers 只支持 queryset,而不支持model的實例,那么怎么實現(xiàn)呢?
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):
"""
如果傳入的是單個對象,區(qū)別于QuerySet的就是
Django不支持序列化單個對象
因此,首先用單個對象來構造一個只有一個對象的數(shù)組
這是就可以看做是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)
參數(shù)中所包含json數(shù)據(jù)
例如,用POST傳過來的參數(shù)中有一個key value鍵值對為
request.POST['update']
= "[{pk:1,name:'changename'},{pk:2,name:'changename2'}]"
要將這個value進行反序列化
則可以使用Django內置的序列化與反序列化
但是問題在于
傳回的有可能是代表單個對象的json字符串
如:
request.POST['update'] = "{pk:1,name:'changename'}"
這是,由于Django無法處理單個對象
因此要做適當?shù)奶幚?
將其模擬成一個數(shù)組,也就是用'[]'進行包圍
再進行反序列化
"""
if json[0] == '[':
return deserialize('json',json)
else:
return deserialize('json','[' + json +']')
def getJson(**args):
""" 使用MyEncoder這個自定義的規(guī)則類來序列化對象
"""
result = dict(args)
return simplejson.dumps(result,cls=MyEncoder)
在上面的例子中,自定義了一個序列化規(guī)則類MyEncoder,用來處理集合或者集合對象,然后實現(xiàn)了一個可變參數(shù)的工具方法getJson,用于傳入多個參數(shù),并將其一同序列化。另外還有一個反序列化對象的方法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]]))
現(xiàn)在用django查出數(shù)據(jù),并轉換成json
row=models.Category.objects.get(autoid=23) print row.toJSON()
你會發(fā)現(xiàn),成功轉換了。當然,這個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. 定義
比如我們創(chuàng)建一個BookInfoSerializer
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數(shù)據(jù)序列化器"""
class Meta:
model = BookInfo
fields = '__all__'
model 指明參照哪個模型類
fields 指明為模型類的哪些字段生成
2. 指定字段
1) 使用fields來明確字段,__all__表名包含所有字段,也可以寫明具體哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數(shù)據(jù)序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')
2) 使用exclude可以明確排除掉哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數(shù)據(jù)序列化器"""
class Meta:
model = BookInfo
exclude = ('image',)
3) 默認ModelSerializer使用主鍵作為關聯(lián)字段,但是我們可以使用depth來簡單的生成嵌套表示,depth應該是整數(shù),表明嵌套的層級數(shù)量。如:
class HeroInfoSerializer2(serializers.ModelSerializer):
class Meta:
model = HeroInfo
fields = '__all__'
depth = 1
4) 指明只讀字段
可以通過read_only_fields指明只讀字段,即僅用于序列化輸出的字段
3. 添加額外參數(shù)
我們可以使用extra_kwargs參數(shù)為ModelSerializer添加或修改原有的選項參數(shù)
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數(shù)據(jù)序列化器"""
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 OpenCV圖像指定區(qū)域裁剪的實現(xiàn)
這篇文章主要介紹了Python OpenCV圖像指定區(qū)域裁剪的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-10-10
淺談tf.train.Saver()與tf.train.import_meta_graph的要點
這篇文章主要介紹了淺談tf.train.Saver() 與tf.train.import_meta_graph的要點,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05
jupyter notebook引用from pyecharts.charts import Bar運行報錯
這篇文章主要介紹了jupyter notebook引用from pyecharts.charts import Bar運行報錯,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04
Windows 安裝 Anaconda3+PyCharm的方法步驟
這篇文章主要介紹了Windows 安裝 Anaconda3+PyCharm的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-06-06

