:::tip 本章概要 代码生成引擎的工作原理,包括配置解析、模板渲染、文件写入和自动注册的完整流程。 ::: # 代码生成引擎 `generator_config.py` 中的 `CodeGenerator` 类是代码生成器的执行层,负责接收配置字典、渲染模板、写入文件、自动注册路由和菜单。 ## 核心类:CodeGenerator ```python from generator_config import CodeGenerator generator = CodeGenerator(config) generator.generate() # 交互模式(询问迁移和菜单创建) generator.generate(auto=True) # 自动模式(Web 界面调用) ``` ### 构造参数 | 参数 | 说明 | |:----|:----| | `config` | 配置字典(由 `TableSchemaParser.parse()` 或 JSON 文件提供) | 构造时自动: - 设置模板目录:`public/templates/` - 设置输出目录:`application/{app_name}/` - 初始化 Jinja2 模板环境(`trim_blocks=True`, `lstrip_blocks=True`) ## generate() 主方法 ### 执行流程 ``` 步骤1: 创建输出目录 application/{app_name}/ │ 步骤2: 准备模板上下文 _prepare_context() │ - 处理字段信息、选项、标识 │ - 分类字段:form_fields / list_fields / filter_fields │ 步骤3: 渲染后端模板并写入文件 │ - models.py (ORM 模型) │ - forms.py (Django 表单验证) │ - services.py (业务逻辑层) │ - views.py (视图层) │ - urls.py (路由配置) │ - apps.py (应用配置) │ - admin.py (后台管理) │ 步骤3.5: 创建 __init__.py 和 migrations/__init__.py │ 步骤3.6: 更新 settings.py 的 INSTALLED_APPS │ - 自动追加 'application.{app_name}' │ 步骤3.7: 更新 application/urls.py │ - 自动追加路由配置 │ 步骤4: 渲染前端模板并写入文件 │ - ui/ 或 ui2/ 目录下的 Vue 组件 │ - API 接口文件 │ 步骤5: 数据库迁移(仅交互模式) │ - python manage.py makemigrations │ - python manage.py migrate │ 步骤6: 创建菜单权限节点 - 主菜单节点(type=0) - 8 个权限节点(type=1) ``` ### 参数 | 参数 | 说明 | |:----|:----| | `auto` | 自动模式(True: 跳过交互确认,直接执行迁移和创建菜单) | ## 模板上下文 ### _prepare_context() 准备后端模板的渲染上下文: | 变量 | 类型 | 说明 | |:----|:----|:----| | `app_name` | str | 模块名(如 `example`) | | `module_comment` | str | 中文名(如 `案例`) | | `module_name` | str | 模块名称(下划线移除) | | `model_class_name` | str | 类名(如 `Example`) | | `model_class_name_camel` | str | 驼峰类名(首字母小写) | | `route_prefix` | str | 路由前缀 | | `permission_prefix` | str | 权限前缀(如 `sys:example`) | | `display_field` | str | 显示字段(如 `name`) | | `has_sort` | bool | 有排序字段 | | `has_status` | bool | 有状态字段 | | `has_unique_code` | bool | 有唯一编码字段 | | `has_image_field` | bool | 有图片字段 | | `has_rich_text_field` | bool | 有富文本字段 | | `fields` | list | 全部字段 | | `form_fields` | list | 表单字段 | | `list_fields` | list | 列表显示字段 | | `filter_fields` | list | 筛选字段 | | `filterable_fields` | list | 可过滤字段 | | `searchable_fields` | list | 可搜索字段 | | `editable_fields` | list | 可编辑字段 | ### _prepare_vue_context() 在后端上下文基础上扩展前端专用变量: | 变量 | 类型 | 说明 | |:----|:----|:----| | `api_path` | str | API 路径(如 `tool/example`) | | `has_export` | bool | 有导出功能 | | `is_tree_structure` | bool | 是否树形结构 | | `parent_id_field` | str | 父级字段名 | | `has_search_form` | bool | 显示搜索表单 | | `show_selection` | bool | 显示复选框(树形结构) | ## 文件生成 ### 后端文件 | 模板 | 输出路径 | 说明 | |:----|:----|:----| | `models.py.tpl` | `application/{name}/models.py` | ORM 模型 | | `forms.py.tpl` | `application/{name}/forms.py` | Django 表单验证 | | `services.py.tpl` | `application/{name}/services.py` | 业务逻辑层 | | `views.py.tpl` | `application/{name}/views.py` | 视图层 | | `urls.py.tpl` | `application/{name}/urls.py` | 路由配置 | | `apps.py.tpl` | `application/{name}/apps.py` | 应用配置 | | `admin.py.tpl` | `application/{name}/admin.py` | 后台管理 | ### 前端文件(普通列表) | 模板 | 输出路径 | |:----|:----| | `ui/index.vue.tpl` | `ui/src/views/tool/{name}/index.vue` | | `ui/edit.vue.tpl` | `ui/src/views/tool/{name}/edit.vue` | | `ui/detail.vue.tpl` | `ui/src/views/tool/{name}/detail.vue` | | `ui/columns.ts.tpl` | `ui/src/views/tool/{name}/columns.ts` | | `ui/querySchemas.ts.tpl` | `ui/src/views/tool/{name}/querySchemas.ts` | | `ui/api.ts.tpl` | `ui/src/api/tool/{name}.ts` | ### 前端文件(树状列表) 当表包含 `parent_id` / `pid` 字段时,自动切换为树形模板: | 模板 | 输出路径 | |:----|:----| | `ui2/index.vue.tpl` | `ui/src/views/tool/{name}/index.vue` | | `ui2/edit.vue.tpl` | `ui/src/views/tool/{name}/edit.vue` | | `ui2/detail.vue.tpl` | `ui/src/views/tool/{name}/detail.vue` | | `ui2/columns.ts.tpl` | `ui/src/views/tool/{name}/columns.ts` | | `ui/api.ts.tpl` | `ui/src/api/tool/{name}.ts` | 树状列表与普通列表共用 `api.ts.tpl`。 ## 自动注册 ### 应用注册 `_update_installed_apps()` 在 `application/settings.py` 的 `INSTALLED_APPS` 列表末尾追加: ```python 'application.example', # 案例管理 ``` 幂等操作:如果已存在,跳过。 ### 路由注册 `_update_main_urls()` 在 `application/urls.py` 的 `urlpatterns` 列表末尾追加: ```python # 案例模块路由 # 访问地址: /example/ path('example/', include('application.example.urls')), ``` 路由前缀支持下划线转斜杠:`order_item` -> `order/item/`。 幂等操作:如果路由已存在,跳过。 ### 菜单创建 `_create_permission_nodes()` 在数据库中创建: 1. **主菜单**(type=0):模块入口菜单 - name: 模块中文名 - path: `/{menu_group}/{module_path}` - component: `/{menu_group}/{module_path}/index` - parent_id: 配置中的 `parent_menu_id` 2. **权限节点**(type=1)x 8 个: | 排序 | 权限名称 | 权限标识 | |:----|:----|:----| | 1 | 查询分页 | `{prefix}:page` | | 5 | 查询列表 | `{prefix}:list` | | 10 | 查询详情 | `{prefix}:detail` | | 15 | 添加 | `{prefix}:add` | | 20 | 更新 | `{prefix}:update` | | 25 | 设置状态 | `{prefix}:status` | | 30 | 删除 | `{prefix}:delete` | | 35 | 批量删除 | `{prefix}:batchDelete` | 幂等操作:如果主菜单已存在(path + type 匹配),更新信息并删除旧权限节点后重建。 ## 总结 代码生成引擎根据配置字典,通过 Jinja2 模板渲染生成后端(models/forms/services/views/urls/apps/admin)和前端(index.vue/edit.vue/columns.ts/querySchemas.ts/api.ts)全套代码,生成后自动注册应用、路由和权限。