Django:按字段类型处理模型对象字段并实现手动序列化
Django 按字段类型手动序列化模型对象为字典(教学场景)
以下是针对教学需求实现的通用手动序列化函数,可按字段类型处理ManyToMany、OneToMany(反向关联)、FileField/ImageField及普通字段,将模型对象转为JSON可序列化字典:
from django.db import models from datetime import datetime def obj_to_dict(obj): obj_dict = {} # 获取模型所有字段,包含关联字段 fields = obj._meta.get_fields() for field in fields: # 跳过自动生成的非具体字段(比如某些反向关联的隐式字段) if field.auto_created and not field.concrete: continue field_name = field.name field_value = getattr(obj, field_name, None) # 处理反向关联(OneToMany:其他模型外键指向当前模型) if field.one_to_many: # 反向关联字段默认返回QuerySet,序列化每个关联对象 related_objs = field_value.all() obj_dict[field_name] = [obj_to_dict(item) for item in related_objs] continue # 处理ManyToMany字段 if isinstance(field, models.ManyToManyField): # ManyToMany字段同样返回QuerySet,序列化每个关联对象 m2m_objs = field_value.all() obj_dict[field_name] = [obj_to_dict(item) for item in m2m_objs] continue # 处理外键关联(ForeignKey) if isinstance(field, models.ForeignKey): if field_value: # 可选择仅序列化关联对象的id和标识,或递归序列化完整对象 obj_dict[field_name] = { "id": field_value.id, "name": str(field_value) } else: obj_dict[field_name] = None continue # 处理FileField/ImageField if isinstance(field, models.FileField): if field_value: # 存储文件的访问URL,而非本地路径 obj_dict[field_name] = field_value.url else: obj_dict[field_name] = None continue # 处理普通字段:适配JSON可序列化类型 if isinstance(field_value, datetime): # 日期时间转ISO格式字符串 obj_dict[field_name] = field_value.isoformat() else: # 其他普通字段直接取值,None则保留None obj_dict[field_name] = field_value return obj_dict
关键逻辑说明:
- 反向关联判断:通过
field.one_to_many识别,这类字段是其他模型外键指向当前模型时自动生成的反向属性,调用all()获取关联对象集合后递归序列化。 - ManyToMany字段:直接通过
isinstance判断类型,同样处理关联对象集合。 - 外键字段:这里选择序列化关联对象的
id和字符串标识(str()),教学场景下也可改为递归调用obj_to_dict获取完整对象数据。 - 文件字段:存储文件的访问URL而非本地路径,更符合JSON序列化的实际使用场景。
- 普通字段:针对
datetime这类JSON不可序列化的类型,转为ISO格式字符串;其他类型直接取值。
使用示例:
假设你有Book和Author模型,Author与Book是一对多关联,Book有tags(ManyToMany)和cover(ImageField)字段,调用方式如下:
author = Author.objects.first() author_dict = obj_to_dict(author)
内容的提问来源于stack exchange,提问作者azzam
相关产品推荐
相关产品推荐

