当前位置: 移动技术网 > IT编程>脚本编程>Python > Django model序列化为json的方法示例

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

2018年11月08日  | 移动技术网IT编程  | 我要评论

女王之刃ol官网,白果有什么作用,水景喷泉设备

本文环境

  • 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 models
import json


class 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()

使用方法:

models的所有类都继承basemodel类,然后调用此类的tojson()方法即可

注意,不知为何,self._meta.fields中没有包含manytomanyfield字段,因而需要重写getmtmfield方法。例子如下:

class book(basemodel):
  name = models.charfield(max_length=50)
  authors = models.manytomanyfield(author)
  publish = models.foreignkey(publisher, on_delete=models.set_null, blank=true, null=true)
  page = models.integerfield(default=0) # 页数
  introduction = models.charfield(max_length=500)
  booktype = models.manytomanyfield(booktype, null=true, blank=true)
  booktag = models.manytomanyfield(booktag, null=true, blank=true)
  evaluation = models.floatfield()
  coverurl = models.charfield(max_length=100, null=true, blank=true)

  def getmtmfield(self):
    return ['booktype', 'booktag']

结果:

{
  "id":4,
  "name":"django从入门到放弃",
  "page":123,
  "introduction":"introduction",
  "evaluation":1,
  "booktype":[
    {
      "id":1,
      "name":"类型"
    }
  ],
  "booktag":[
    {
      "id":2,
      "name":"tag"
    }
  ]
}

后记

源码有引用,即getdict方法中的第一个for循环,但懒得找原链接了,望见谅,特此声明;

  • 本人python新手,代码多有不规范之处,望见谅;
  • 代码不精,但是也希望能帮到你_;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网