内容简介:平常的开发过程中不免遇到需要把model转成字典的需求,尤其是现在流行前后端分离架构,Json格式几乎成了前后端之间数据交换的标准,这种model转dict的需求就更多了,本文介绍几种日常使用的方法以供参考,所有例子均基于Django 2.0环境演示model内容如下:需求很简单就是分别把Group和User表中的数据转换成字典格式返回
平常的开发过程中不免遇到需要把model转成字典的需求,尤其是现在流行前后端分离架构,Json格式几乎成了前后端之间数据交换的标准,这种model转dict的需求就更多了,本文介绍几种日常使用的方法以供参考,所有例子均基于Django 2.0环境演示
背景介绍
model内容如下:
class Group(models.Model):
name = models.CharField(max_length=255, unique=True, verbose_name='组名称')
def __str__(self):
return self.name
class User(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
username = models.EmailField(max_length=255, unique=True, verbose_name='用户名')
fullname = models.CharField(max_length=64, null=True, verbose_name='中文名')
is_active = models.BooleanField(default=True, verbose_name='激活状态')
leader = models.ForeignKey('self', null=True, on_delete=models.CASCADE, verbose_name='上级')
group = models.ManyToManyField(Group, null=True, verbose_name='所属组')
def __str__(self):
return self.username
复制代码
需求很简单就是分别把Group和User表中的数据转换成字典格式返回
方法一:直接构建字典
示例代码:
>>> _t = Group.objects.get(id=1)
>>>
>>> dict = {
... 'id': _t.id,
... 'name': _t.name
... }
>>>
>>> print(dict)
{'name': 'GroupA', 'id': 1}
复制代码
这种方法的好处是方便控制最终返回字典value的格式,例如对于User表,我想返回最终的数据是id、创建时间、中文名、上级中文名、所属组名列表的话可以用下边的代码实现
>>> _t = User.objects.get(id=2)
>>>
>>> dict = {
... 'id': _t.id,
... 'create_time': _t.create_time.strftime('%Y-%m-%d %H:%M:%S'),
... 'fullname': _t.fullname if _t.fullname else None,
... 'leader': _t.leader.fullname if _t.leader else None,
... 'group': [ i.name for i in _t.group.all() ],
... }
>>>
>>> print(dict)
{'fullname': '运维咖啡吧', 'group': ['GroupA', 'GroupC', 'GroupE'], 'create_time': '2018-10-12 21:20:19', 'id': 2, 'leader': '公众号'}
>>>
复制代码
缺点也很明显,就是如果一个model字段很多且不需要转换value格式的时候需要写大量冗余的代码,这种问题怎么解决呢?且看下边的方法介绍
方法二:dict
示例代码:
>>> Group.objects.get(id=1).__dict__
{'id': 1, 'name': 'GroupA', '_state': <django.db.models.base.ModelState object at 0x7f68612daef0>}
>>>
>>> User.objects.get(id=1).__dict__
{'is_active': True, '_state': <django.db.models.base.ModelState object at 0x7f68612fa0b8>, 'id': 1, 'username': 'ops@163.com', 'leader_id': None, 'fullname': '公众号', 'update_time': datetime.datetime(2018, 10, 12, 17, 49, 35, 504141), 'create_time': datetime.datetime(2018, 10, 12, 16, 9, 7, 813660)}
复制代码
这种方法优点就是写法简单,容易理解,代码量还少
但会发现多了个没用的 _state 字段,同时Foreignkey字段名多了 _id ,也没有ManyToManyField字段的数据,且不能按需显示输出,当我只需要其中几个字段时会有大量冗余数据
方法三:model_to_dict
示例代码:
>>> model_to_dict(Group.objects.get(id=1))
{'name': 'GroupA', 'id': 1}
>>>
>>> model_to_dict(User.objects.get(id=2))
{'leader': 1, 'is_active': True, 'username': 'ops-coffee@163.com', 'fullname': '运维咖啡吧', 'group': [<Group: GroupA>, <Group: GroupC>, <Group: GroupE>], 'id': 2}
复制代码
这种方法能满足大部分的需求,且输出也较为合理,同时还有两个参数 fields 和 exclude 来配置输出的字段,例如:
>>> model_to_dict(User.objects.get(id=2), fields=['fullname','is_active'])
{'is_active': True, 'fullname': '运维咖啡吧'}
>>>
>>> model_to_dict(User.objects.get(id=2), exclude=['group','leader','id'])
{'fullname': '运维咖啡吧', 'is_active': True, 'username': 'ops-coffee@163.com'}
复制代码
但是会跳过有 editable=False 属性字段的展示,对于有 auto_now_add=True 和 auto_now=True 属性的datetime字段会默认添加 editable=False 隐藏属性,这也是上边两个time相关字段 create_time 和 update_time 转换成dict后不显示的原因,官方相关源码如下:
for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many):
if not getattr(f, 'editable', False):
continue
复制代码
方法四:自定义to_dict
示例代码:
from django.db.models.fields import DateTimeField
from django.db.models.fields.related import ManyToManyField
class User(models.Model):
...
def to_dict(self, fields=None, exclude=None):
data = {}
for f in self._meta.concrete_fields + self._meta.many_to_many:
value = f.value_from_object(self)
if fields and f.name not in fields:
continue
if exclude and f.name in exclude:
continue
if isinstance(f, ManyToManyField):
value = [ i.id for i in value ] if self.pk else None
if isinstance(f, DateTimeField):
value = value.strftime('%Y-%m-%d %H:%M:%S') if value else None
data[f.name] = value
return data
复制代码
执行结果:
>>> User.objects.get(id=2).to_dict()
{'is_active': True, 'update_time': '2018-10-12 21:21:39', 'username': 'ops-coffee@163.com', 'id': 2, 'leader': 1, 'group': [1, 3, 5], 'create_time': '2018-10-12 21:20:19', 'fullname': '运维咖啡吧'}
>>>
>>> User.objects.get(id=2).to_dict(fields=['fullname','is_active','create_time'])
{'is_active': True, 'fullname': '运维咖啡吧', 'create_time': '2018-10-12 21:20:19'}
>>>
>>> User.objects.get(id=2).to_dict(exclude=['group','leader','id','create_time'])
{'is_active': True, 'update_time': '2018-10-12 21:21:39', 'username': 'ops-coffee@163.com', 'fullname': '运维咖啡吧'}
复制代码
拥有 model_to_dict 一样的便利性,同时也解决了不能输出time时间字段(editable=False)的问题,还能对value按照自己需要的格式输出,一举多得 当然拥有便利性的同时需要自己实现 to_dict 的代码,增加了复杂度
如果你觉得文章对你有帮助,请转发分享给更多的人。如果你觉得读的不尽兴,推荐阅读以下文章:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【Python—字典的用法】创建字典的3种方法
- Python 字典(Dictionary) cmp()方法
- Python 字典(Dictionary) len()方法
- Python 字典(Dictionary) str()方法
- Python 字典(Dictionary) type()方法
- Python 字典(Dictionary) clear()方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
An Introduction to the Analysis of Algorithms
Robert Sedgewick、Philippe Flajolet / Addison-Wesley Professional / 1995-12-10 / CAD 67.99
This book is a thorough overview of the primary techniques and models used in the mathematical analysis of algorithms. The first half of the book draws upon classical mathematical material from discre......一起来看看 《An Introduction to the Analysis of Algorithms》 这本书的介绍吧!