Django model序列化为json的方法示例
作者:Van96 发布时间:2022-08-25 01:39:03
本文环境
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新手,代码多有不规范之处,望见谅;
代码不精,但是也希望能帮到你_;
来源:https://www.jianshu.com/p/c3db3cc2c80a
猜你喜欢
- 在Web标准中的页面布局是使用Div配合CSS来实现的。这其中最常用到的就是使整个页面水平居中的效果,这是在页面布局中基本,也是最应该首先掌
- 一般我们可以使用背景图的方式给图片添加阴影,但对于不固定尺寸的图片如何实现呢?我们可以采取“视觉欺骗 * ”——定义渐变边框来实现运行代码框&
- 随着网站访问量的加大,每次从数据库读取都是以效率作为代价的,很多用ACCESS作数据库的更会深有体会,静态页加在搜索时,也会被优先考虑。互联
- ASP实现语音分时问候,其实asp实现这个功能很容易,时间判断一下,在某个时间段就调用某个的背景语音。下面是源代码:
- 本文介绍了使用Application来统计访问网站的在线人数的方法,并介绍了使用Application时应该注意的事项。首先讲明白,用ASP
- PDOStatement::closeCursorPDOStatement::closeCursor — 关闭游标,使语句能再次被执行。(P
- 处理办法,删除该文件,或清空该文件内容;我的处理是清空后,再设置该文件权限为Everyone拒绝访问。
- 下面是代码,如果看不懂,建议先把表格的一些<tr><td>的表格原理弄清楚了,就可以了代码如下:<table&
- 1. 图像轮廓1.1 findContours介绍cv2.findContours(img, mode, method)mode:轮廓检索模
- 相信大家平时都有这样的经历:页面上有一个链接指向服务器一个Word文件,当客户端机器有安装Office时,点击链接将调用Word打开浏览;当
- froglt 的站点:http://www.go2here.net 欢迎转载,请注明出处,未经作者允许,禁止一切商业应用。这是即
- XML被设计用来描述数据,其焦点是数据的内容。HTML被设计用来显示数据,其焦点是数据的外观。  
- 页面重构需要考虑的一个重点是XHTML代码语义化,就算是在无任何CSS样式修饰的情况下也能给他人在阅读时带来便利,甚至可以夸张点说在搜索引擎
- 本文实例为大家分享了js实现鼠标切换图片的具体代码,供大家参考,具体内容如下实现效果,可以利用鼠标移动在对应的小点点上,或者点击左右两侧的箭
- 兼容IE6的第一步就是单独对IE进行兼容,你针对IE6所写的代码只影响IE6;有几种方法可以区分开IE6:IE特有条件注释、CSS选择器、J
- 1、800*600下,网页宽度保持在778以内,就不会出现水平滚动条,高度则视版面和内容决定。2、1024*768下,网页宽度保持在1002
- 一般用 createProcessingInstruction 方法创建处理指令指定参数为 "xml","ve
- 代码如下:CREATE TABLE [dbo].[TbGuidTable]( [TableName] [varchar](50) NOT N
- 异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变
- 本文实例讲述了python循环监控远程端口的方法。分享给大家供大家参考。具体如下:在ip.txt中每行一个ip地址和端口号,代码可循环监控这