首页 > 编程 > Python > 正文

Django model序列化为json的方法示例

2020-02-15 23:13:47
字体:
来源:转载
供稿:网友

本文环境

Python 3.6.5 Django 2.0.4

fix(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()            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表