Django框架:重写model_to_dict,支持对模型中时间字段的序列化,对json字符串的反序列化

一、复制源码,封装成能支持时间类型的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)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值