首次上传完整项目
This commit is contained in:
215
export_meta_tables.py
Normal file
215
export_meta_tables.py
Normal file
@@ -0,0 +1,215 @@
|
||||
import csv
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def init_django():
|
||||
base_dir = Path(__file__).resolve().parent
|
||||
project_root = base_dir / "ZeroCodeProject" / "apis" / "ZeroCodeMain"
|
||||
if not project_root.exists():
|
||||
return None
|
||||
sys.path.insert(0, str(project_root))
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ZeroCodeMain.settings")
|
||||
try:
|
||||
import django
|
||||
|
||||
django.setup()
|
||||
from django.db import connection
|
||||
from BaseApi.models import App, Model, ModelField, ModelSetting
|
||||
except Exception:
|
||||
return None
|
||||
return App, Model, ModelField, ModelSetting, connection
|
||||
|
||||
|
||||
def export_meta_tables(output_dir: str = None) -> None:
|
||||
base_dir = Path(__file__).resolve().parent
|
||||
if output_dir is None:
|
||||
output_path = base_dir
|
||||
else:
|
||||
output_path = Path(output_dir)
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
all_rows = []
|
||||
|
||||
table1 = [
|
||||
["类名", "所在层/文件", "关键字段", "含义"],
|
||||
["App", "BaseApi/models.py", "name, name_cn, module", "定义动态模型所属的应用和模块路径"],
|
||||
["Model", "BaseApi/models.py", "app, name, name_cn", "定义单个动态模型的元数据(名称及所属应用)"],
|
||||
["ModelField", "BaseApi/models.py", "model, name, type, is_show", "定义动态模型中的单个字段及其类型、显示属性"],
|
||||
["ModelSetting", "BaseApi/models.py", "field, name, value", "定义字段的具体配置项(例如 max_length、null 等)"],
|
||||
]
|
||||
|
||||
all_rows.append(["# 元数据类汇总表"])
|
||||
all_rows.extend(table1)
|
||||
all_rows.append([])
|
||||
|
||||
table2 = [
|
||||
["元数据实体", "标识字段", "对应的原对象实体", "关系说明"],
|
||||
["App 记录", "name", "Django 应用(AppConfig)", "确定动态模型注册的命名空间及表名前缀"],
|
||||
["Model 记录", "app + name", "动态 Django 模型类 + 物理数据表", "每条 Model 记录对应一个模型类及一张数据表"],
|
||||
["ModelField 记录", "model + name", "动态模型上的一个字段", "每条记录对应模型上的一个具体字段"],
|
||||
["ModelSetting 记录", "field + name", "字段构造器上的一个关键字参数", "决定字段的单个具体属性(如 max_length、null 等)"],
|
||||
]
|
||||
|
||||
all_rows.append(["# 元数据与原对象映射(概念层面)"])
|
||||
all_rows.extend(table2)
|
||||
all_rows.append([])
|
||||
|
||||
django_models = init_django()
|
||||
if not django_models:
|
||||
all_file = output_path / "meta_all_in_one.csv"
|
||||
with all_file.open("w", newline="", encoding="utf-8-sig") as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerows(all_rows)
|
||||
return
|
||||
|
||||
App, Model, ModelField, ModelSetting, connection = django_models
|
||||
|
||||
model_rows = [
|
||||
[
|
||||
"app_name",
|
||||
"app_name_cn",
|
||||
"app_module",
|
||||
"model_name",
|
||||
"model_name_cn",
|
||||
"django_app_label",
|
||||
"django_model_class",
|
||||
"db_table_name",
|
||||
]
|
||||
]
|
||||
|
||||
for m in Model.objects.select_related("app").all():
|
||||
app = m.app
|
||||
django_app_label = app.name
|
||||
django_model_class = django_app_label + "." + m.name
|
||||
db_table_name = django_app_label + "_" + m.name
|
||||
model_rows.append(
|
||||
[
|
||||
app.name,
|
||||
app.name_cn,
|
||||
app.module,
|
||||
m.name,
|
||||
m.name_cn,
|
||||
django_app_label,
|
||||
django_model_class,
|
||||
db_table_name,
|
||||
]
|
||||
)
|
||||
|
||||
all_rows.append(["# 元数据模型与原对象模型一对一映射(实例层面)"])
|
||||
all_rows.extend(model_rows)
|
||||
all_rows.append([])
|
||||
|
||||
settings_map = {}
|
||||
for s in ModelSetting.objects.select_related("field").all():
|
||||
field_id = s.field_id
|
||||
pair = s.name + "=" + s.value
|
||||
settings_map.setdefault(field_id, []).append(pair)
|
||||
|
||||
field_rows = [
|
||||
[
|
||||
"app_name",
|
||||
"model_name",
|
||||
"field_name",
|
||||
"field_name_cn",
|
||||
"field_type",
|
||||
"is_show",
|
||||
"settings",
|
||||
]
|
||||
]
|
||||
|
||||
for f_obj in ModelField.objects.select_related("model", "model__app").all():
|
||||
app = f_obj.model.app
|
||||
model = f_obj.model
|
||||
merged_settings = ";".join(settings_map.get(f_obj.id, []))
|
||||
field_rows.append(
|
||||
[
|
||||
app.name,
|
||||
model.name,
|
||||
f_obj.name,
|
||||
f_obj.name_cn,
|
||||
f_obj.type,
|
||||
"1" if f_obj.is_show else "0",
|
||||
merged_settings,
|
||||
]
|
||||
)
|
||||
|
||||
all_rows.append(["# 字段级元数据与原对象字段映射(字段层面)"])
|
||||
all_rows.extend(field_rows)
|
||||
all_rows.append([])
|
||||
|
||||
table_rows = [["table_name", "model_class", "column_count"]]
|
||||
model_map = {
|
||||
"BaseApi_app": App,
|
||||
"BaseApi_model": Model,
|
||||
"BaseApi_modelfield": ModelField,
|
||||
"BaseApi_modelsetting": ModelSetting,
|
||||
}
|
||||
for table_name, model_cls in model_map.items():
|
||||
meta = model_cls._meta
|
||||
concrete_fields = [f for f in meta.get_fields() if getattr(f, "concrete", False) and not getattr(f, "many_to_many", False)]
|
||||
table_rows.append(
|
||||
[
|
||||
meta.db_table,
|
||||
meta.label,
|
||||
str(len(concrete_fields)),
|
||||
]
|
||||
)
|
||||
|
||||
all_rows.append(["# 元数据相关数据库表结构总览"])
|
||||
all_rows.extend(table_rows)
|
||||
all_rows.append([])
|
||||
|
||||
column_rows = [
|
||||
["table_name", "model_class", "column_name", "field_type", "null", "primary_key", "default"]
|
||||
]
|
||||
for model_cls in [App, Model, ModelField, ModelSetting]:
|
||||
meta = model_cls._meta
|
||||
for field in meta.get_fields():
|
||||
if not getattr(field, "concrete", False) or getattr(field, "many_to_many", False):
|
||||
continue
|
||||
default_value = field.default
|
||||
if callable(default_value):
|
||||
default_value = ""
|
||||
column_rows.append(
|
||||
[
|
||||
meta.db_table,
|
||||
meta.label,
|
||||
field.name,
|
||||
field.get_internal_type(),
|
||||
"1" if field.null else "0",
|
||||
"1" if field.primary_key else "0",
|
||||
str(default_value),
|
||||
]
|
||||
)
|
||||
|
||||
all_rows.append(["# 元数据相关数据库字段结构明细"])
|
||||
all_rows.extend(column_rows)
|
||||
all_rows.append([])
|
||||
|
||||
for model_cls, section_title in [
|
||||
(App, "# BaseApi_app 表数据"),
|
||||
(Model, "# BaseApi_model 表数据"),
|
||||
(ModelField, "# BaseApi_modelfield 表数据"),
|
||||
(ModelSetting, "# BaseApi_modelsetting 表数据"),
|
||||
]:
|
||||
meta = model_cls._meta
|
||||
field_names = [f.name for f in meta.fields]
|
||||
rows = [field_names]
|
||||
qs = model_cls.objects.all().values_list(*field_names)
|
||||
for row in qs:
|
||||
rows.append([str(v) for v in row])
|
||||
all_rows.append([section_title])
|
||||
all_rows.extend(rows)
|
||||
all_rows.append([])
|
||||
|
||||
all_file = output_path / "meta_all_in_one.csv"
|
||||
with all_file.open("w", newline="", encoding="utf-8-sig") as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerows(all_rows)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
export_meta_tables()
|
||||
|
||||
14
meta_all_in_one.csv
Normal file
14
meta_all_in_one.csv
Normal file
@@ -0,0 +1,14 @@
|
||||
# 元数据类汇总表
|
||||
类名,所在层/文件,关键字段,含义
|
||||
App,BaseApi/models.py,"name, name_cn, module",定义动态模型所属的应用和模块路径
|
||||
Model,BaseApi/models.py,"app, name, name_cn",定义单个动态模型的元数据(名称及所属应用)
|
||||
ModelField,BaseApi/models.py,"model, name, type, is_show",定义动态模型中的单个字段及其类型、显示属性
|
||||
ModelSetting,BaseApi/models.py,"field, name, value",定义字段的具体配置项(例如 max_length、null 等)
|
||||
|
||||
# 元数据与原对象映射(概念层面)
|
||||
元数据实体,标识字段,对应的原对象实体,关系说明
|
||||
App 记录,name,Django 应用(AppConfig),确定动态模型注册的命名空间及表名前缀
|
||||
Model 记录,app + name,动态 Django 模型类 + 物理数据表,每条 Model 记录对应一个模型类及一张数据表
|
||||
ModelField 记录,model + name,动态模型上的一个字段,每条记录对应模型上的一个具体字段
|
||||
ModelSetting 记录,field + name,字段构造器上的一个关键字参数,决定字段的单个具体属性(如 max_length、null 等)
|
||||
|
||||
|
Reference in New Issue
Block a user