本文環境
Python 3.6.5 Django 2.0.4fix(2018.5.19):最近得知Django 的model基類需要聲明為abstract,故在原來的代碼加入abstract聲明,以免誤導
在Django中,關于如何將model類序列化為json,一般的話有兩a器
將model類轉為字典,再使用json庫的dumps方法轉為json
第一種方法就不多講了,直接去看官方文檔就好啦
一般來說,官方提供的方法應該都是比較好用和穩定的,然而,使用官方的序列化器卻問題不少:
格式丑陋,格式如下,一言難盡:
[ { "pk": "4b678b301dfd8a4e0dad910de3ae245b", "model": "sessions.session", "fields": { "expire_date": "2013-01-16T08:16:59.844Z", ... } }]
是的,其中pk指的是默認主鍵,model指的是該object的model類型,然后fields才是obj的各種字段...真的是不知如何評價了
不能很好地支持list 對于一些外鍵(包括ManyToManyField等)不是很友好 甚至對于自身的DateField也沒有很好的支持數了一通官方序列化器的缺點,當然了,上面的幾個點肯定是有解決方案的,但是啊,我確實不想折騰了嚶嚶嚶。
于是扔出我的解決方案:
新建一個類BaseModel,此類繼承于官方的model類django.db.models.Model 在著個BaseModel中,聲明一個方法,此方法用于生成關于這個object的字典 使用這個object的字典生成json關于生成object的字典的策略是這樣的:
通過反射獲取這個object的所有字段名 根據字段名獲得某個字段field 如果filed的類型的是int、float、str的話,直接將以 "字段名":字段值 的形式放入字典中 若field的類型是datetime或者date的話,使用date的方式處理,然后放入字典 若field的類型是BaseModel的話,那么就調用該field的getDict方法遞歸獲得該field對應的字典,然后放入字典中 若field的類型是ManyToMany類型,在具體草種中我們使用這個field的all方法來這個field的所有object,然后也是通過getDict方法將其放入到字典中源碼及使用方法
from django.db import modelsimport jsonclass BaseModel(models.Model): class Meta: abstract = True # 返回self._meta.fields中沒有的,但是又是需要的字段名的列表 # 形如['name','type'] def getMtMField(self): pass # 返回需要在json中忽略的字段名的列表 # 形如['password'] def getIgnoreList(self): pass def isAttrInstance(self, attr, clazz): return isinstance(getattr(self, attr), clazz) def getDict(self): fields = [] for field in self._meta.fields: fields.append(field.name) d = {} import datetime for attr in fields: if isinstance(getattr(self, attr), datetime.datetime): d[attr] = getattr(self, attr).strftime('%Y-%m-%d %H:%M:%S') elif isinstance(getattr(self, attr), datetime.date): d[attr] = getattr(self, attr).strftime('%Y-%m-%d') # 特殊處理datetime的數據 elif isinstance(getattr(self, attr), BaseModel): d[attr] = getattr(self, attr).getDict() # 遞歸生成BaseModel類的dict elif self.isAttrInstance(attr, int) or self.isAttrInstance(attr, float) / or self.isAttrInstance(attr, str): d[attr] = getattr(self, attr) # else: # d[attr] = getattr(self, attr) mAttr = self.getMtMField() if mAttr is not None: for m in mAttr: if hasattr(self, m): attlist = getattr(self, m).all() l = [] for attr in attlist: if isinstance(attr, BaseModel): l.append(attr.getDict()) else: dic = attr.__dict__ if '_state' in dic: dic.pop('_state') l.append(dic) d[m] = l # 由于ManyToMany類不能存在于_meat.fields,因而子類需要在getMtMFiled中返回這些字段 if 'basemodel_ptr' in d: d.pop('basemodel_ptr') ignoreList = self.getIgnoreList() if ignoreList is not None: for m in ignoreList: if d.get(m) is not None: d.pop(m) # 移除不需要的字段 return d def toJSON(self): import json return json.dumps(self.getDict(), ensure_ascii=False).encode('utf-8').decode()
新聞熱點
疑難解答