一、复制源码,封装成能支持时间类型的model_to_dict
源码对DateField和DateTimeField 字段是不支持的
修改源码,使用自己的代码处理这两种类型的字段数据
-
DateField , 设置的fmt = '%y-%m-%d'
-
DateTimeFiled, 设置的fmt='%Y-%m-%d %H:%M:%S'
-
CharField或TextField字段,有些时候进行json.dumps,存的是json字符串,想要json.loads回来
-
可能需要替换某些字段展示到前端的名字,如:数据库字段name,在前端需要展示成student_name
-
可能需要新增数据库不存在的字段数据,但是前端需要或后端需要,一般用于做标识的
from itertools import chain
from django.db.models.fields import DateTimeField, DateField, CharField, TextField
from datetime import datetime
from django.db.models import Model
import json
'''
封装django自带的将模型转成字典的方法,新增处理DateTimeField和DateField
'''
def model_to_dict(instance, fields=None, exclude=None, replace=None, default=None):
"""
:params instance: 模型对象,不能是queryset数据集
:params fields: 指定要展示的字段数据,('字段1','字段2')
:params exclude: 指定排除掉的字段数据,('字段1','字段2')
:params replace: 将字段名字修改成需要的名字,{'数据库字段名':'前端展示名'}
:params default: 新增不存在的字段数据,{'字段':'数据'}
"""
# 对传递进来的模型对象校验
if not isinstance(instance, Model):
raise Exception('model_to_dict接收的参数必须是模型对象')
# 对替换数据库字段名字校验
if replace and type(replace) == dict:
for replace_field in replace.values():
if hasattr(instance, replace_field):
raise Exception(f'model_to_dict,要替换成{replace_field}字段已经存在了')
# 对要新增的默认值进行校验
if default and type(default) == dict:
for default_key in default.keys():
if hasattr(instance, default_key):
raise Exception(f'model_to_dict,要新增默认值,但字段{default_key}已经存在了')
opts = instance._meta
data = {}
for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many):
# 源码下:这块代码会将时间字段剔除掉,我加上一层判断,让其不再剔除时间字段
if not getattr(f, 'editable', False):
if type(f) == DateField or type(f) == DateTimeField:
pass
else:
continue
# 如果fields参数传递了,要进行判断
if fields is not None and f.name not in fields:
continue
# 如果exclude 传递了,要进行判断
if exclude and f.name in exclude:
continue
key = f.name
# 获取字段对应的数据
if type(f) == DateTimeField:
# 字段类型是,DateTimeFiled 使用自己的方式操作
value = getattr(instance, key)
value = datetime.strftime(value, '%Y-%m-%d %H:%M:%S')
elif type(f) == DateField:
# 字段类型是,DateFiled 使用自己的方式操作
value = getattr(instance, key)
value = datetime.strftime(value, '%Y-%m-%d')
elif type(f) == CharField or type(f) == TextField:
# 字符串数据是否可以进行序列化,转成python结构数据
value = getattr(instance, key)
try:
value = json.loads(value)
except Exception as _:
value = value
else:#其他类型的字段
# value = getattr(instance, key)
key = f.name
value = f.value_from_object(instance)
# data[f.name] = f.value_from_object(instance)
# 1、替换字段名字
if replace and key in replace.keys():
key = replace.get(key)
data[key] = value
#2、新增默认的字段数据
if default:
data.update(default)
return data
二、封装一个model_to_list, 支持queryset的数据
def model_to_list(data: list, fields=None, exclude=None, replace=None, default=None):
'''
将queryset转成[{},{}] 格式
:param data:
:return:
'''
all_list = []
if len(data) == 0:
return all_list
if not isinstance(data[0],Model):
#第一个如果不是模型对象就报错
raise Exception('model_to_list,内部元素必须是模型对象')
for dic in data:
try:
all_list.append(model_to_dict(dic, fields=fields, exclude=exclude, replace=replace, default=default))
except Exception as e:
raise ValueError(str(e))
return all_list
使用:
1、model_to_dict user = models.User.objects.filter(id=10).first() data_dic = model_to_dict(user) 2、model_to_list users = models.User.objects.filter(is_delete=False) data_lis = model_to_list(users)