You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写通用Python脚本导出Django项目所有模型架构至Excel?

通用Django模型架构导出Excel脚本实现方案

核心思路

不用手动递归解析models.py文件,直接利用Django自身的ORM元数据API提取模型信息,既可靠又能避免手动解析的边缘问题。整体流程:

  1. 遍历指定的所有Django微服务项目根目录
  2. 为每个项目动态加载Django环境,获取所有注册的模型
  3. 提取每个模型的字段元数据(类型、约束、关联关系等)
  4. 将每个模型的数据写入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)

关键边缘情况处理

  1. 抽象模型与代理模型:

    • 默认跳过抽象模型(不会生成数据库表),如需导出可删除if model._meta.abstract: continue判断
    • 代理模型可通过model._meta.proxy标识,可在工作表名添加标注(如sheet_name += " [代理]")
  2. 自定义字段:

    • 使用field.get_internal_type()获取字段的标准类型(如自定义CharField会返回"CharField")
    • 如需显示自定义字段类名,替换为field.__class__.__name__
  3. 工作表名长度限制:

    • openpyxl限制工作表名最多31个字符,脚本会自动截断过长的名称并添加省略号
  4. 多项目环境隔离:

    • 每个项目处理完成后,会清理sys.path和Django环境变量,重置配置状态,避免不同项目的依赖/配置冲突
  5. 关联字段处理:

    • 自动识别外键、一对一、多对多字段,添加关联模型名称标注
    • 跳过反向关联字段(如外键的反向引用),只保留模型中显式定义的字段
  6. 依赖兼容问题:

    • 若不同微服务使用不同Django版本或依赖,建议为每个项目单独创建虚拟环境,通过subprocess调用对应环境的Python执行脚本(可自行扩展该逻辑)

使用说明

  1. 替换SERVICE_DIRS为你的实际微服务项目根目录列表
  2. 确保所有项目的INSTALLED_APPS包含需要导出的App
  3. 运行脚本前,确保已安装所有项目的依赖(或使用统一虚拟环境)

内容的提问来源于stack exchange,提问作者Anshuman Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:04:57