django model object序列化例項
提到序列化與反序列化,通常會想到 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','bpub_date','bread','bcomment') extra_kwargs = { 'bread': {'min_value': 0,'required': True},'bcomment': {'min_value': 0,}
以上這篇django model object序列化例項就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。