如何编写通用Python脚本导出Django项目所有模型架构至Excel?
通用Django模型架构导出Excel脚本实现方案
核心思路
不用手动递归解析models.py文件,直接利用Django自身的ORM元数据API提取模型信息,既可靠又能避免手动解析的边缘问题。整体流程:
- 遍历指定的所有Django微服务项目根目录
- 为每个项目动态加载Django环境,获取所有注册的模型
- 提取每个模型的字段元数据(类型、约束、关联关系等)
- 将每个模型的数据写入Excel的独立工作表
实现代码
首先安装依赖:
pip install django openpyxl
完整脚本:
import os import sys import django from django.apps import apps import openpyxl from django.db import models def get_field_details(field): """提取单个字段的详细信息""" details = { 'field_name': field.name, 'field_type': field.get_internal_type(), 'max_length': getattr(field, 'max_length', None), 'null': field.null, 'blank': field.blank, 'primary_key': field.primary_key, 'unique': field.unique, 'help_text': field.help_text.strip() if field.help_text else None, 'related_model': None } # 处理关联字段 if isinstance(field, (models.ForeignKey, models.OneToOneField)): details['related_model'] = field.related_model.__name__ elif isinstance(field, models.ManyToManyField): details['related_model'] = field.related_model.__name__ details['field_type'] = f"{details['field_type']} (多对多)" return details def process_django_project(project_root, workbook): """处理单个Django项目,提取模型信息并写入Excel""" project_name = os.path.basename(project_root) settings_module = f"{project_name}.settings" # 配置Django环境 os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module) sys.path.insert(0, project_root) try: django.setup() # 遍历所有已注册的App和模型 for app_config in apps.get_app_configs(): for model in app_config.get_models(): # 跳过抽象模型(可根据需求取消注释) if model._meta.abstract: continue # 生成工作表名(避免超过openpyxl的31字符限制) sheet_name = f"{app_config.label}.{model.__name__}" if len(sheet_name) > 31: sheet_name = f"{sheet_name[:28]}..." # 创建工作表并写入表头 sheet = workbook.create_sheet(title=sheet_name) headers = [ '字段名', '字段类型', '最大长度', '是否可为空', '是否允许空白', '主键', '唯一约束', '帮助文本', '关联模型' ] sheet.append(headers) # 遍历模型字段并写入数据 for field in model._meta.get_fields(): # 跳过非具体字段(如反向关联) if not field.concrete and not isinstance(field, models.ManyToManyField): continue field_info = get_field_details(field) row = [ field_info['field_name'], field_info['field_type'], field_info['max_length'], '是' if field_info['null'] else '否', '是' if field_info['blank'] else '否', '是' if field_info['primary_key'] else '否', '是' if field_info['unique'] else '否', field_info['help_text'] or '', field_info['related_model'] or '' ] sheet.append(row) print(f"已处理项目: {project_root}") except Exception as e: print(f"处理项目 {project_root} 失败: {str(e)}") finally: # 清理环境,避免影响下一个项目 sys.path.pop(0) if 'DJANGO_SETTINGS_MODULE' in os.environ: del os.environ['DJANGO_SETTINGS_MODULE'] # 重置Django配置状态 from django.conf import settings settings._wrapped = None def main(service_root_dirs, output_path): """主函数:遍历所有微服务项目并导出Excel""" workbook = openpyxl.Workbook() # 删除默认创建的空白工作表 workbook.remove(workbook.active) for dir_path in service_root_dirs: # 判断是否为Django项目(存在manage.py) if os.path.exists(os.path.join(dir_path, 'manage.py')): process_django_project(dir_path, workbook) else: print(f"跳过非Django目录: {dir_path}") workbook.save(output_path) print(f"导出完成!文件已保存至: {output_path}") if __name__ == '__main__': # 配置你的微服务项目根目录列表 SERVICE_DIRS = [ "/opt/services/user-service", "/opt/services/order-service", "/opt/services/product-service" ] # 输出Excel路径 OUTPUT_FILE = "django_models_architecture.xlsx" main(SERVICE_DIRS, OUTPUT_FILE)
关键边缘情况处理
抽象模型与代理模型:
- 默认跳过抽象模型(不会生成数据库表),如需导出可删除
if model._meta.abstract: continue判断 - 代理模型可通过
model._meta.proxy标识,可在工作表名添加标注(如sheet_name += " [代理]")
- 默认跳过抽象模型(不会生成数据库表),如需导出可删除
自定义字段:
- 使用
field.get_internal_type()获取字段的标准类型(如自定义CharField会返回"CharField") - 如需显示自定义字段类名,替换为
field.__class__.__name__
- 使用
工作表名长度限制:
- openpyxl限制工作表名最多31个字符,脚本会自动截断过长的名称并添加省略号
多项目环境隔离:
- 每个项目处理完成后,会清理
sys.path和Django环境变量,重置配置状态,避免不同项目的依赖/配置冲突
- 每个项目处理完成后,会清理
关联字段处理:
- 自动识别外键、一对一、多对多字段,添加关联模型名称标注
- 跳过反向关联字段(如外键的反向引用),只保留模型中显式定义的字段
依赖兼容问题:
- 若不同微服务使用不同Django版本或依赖,建议为每个项目单独创建虚拟环境,通过
subprocess调用对应环境的Python执行脚本(可自行扩展该逻辑)
- 若不同微服务使用不同Django版本或依赖,建议为每个项目单独创建虚拟环境,通过
使用说明
- 替换
SERVICE_DIRS为你的实际微服务项目根目录列表 - 确保所有项目的
INSTALLED_APPS包含需要导出的App - 运行脚本前,确保已安装所有项目的依赖(或使用统一虚拟环境)
内容的提问来源于stack exchange,提问作者Anshuman Mishra
相关产品推荐
相关产品推荐

