6.5 KiB
6.5 KiB
:::tip 本章概要 代码生成引擎的工作原理,包括配置解析、模板渲染、文件写入和自动注册的完整流程。 :::
代码生成引擎
src/modules/generator/code_generator.py 是代码生成器的执行层,负责接收配置字典、渲染模板、写入文件、自动注册路由和菜单。
核心类:CodeGenerator
from modules.generator.code_generator import CodeGenerator
generator = CodeGenerator(config)
generator.generate(auto=True)
构造参数
| 参数 | 说明 |
|---|---|
config |
配置字典(由 parser.parse() 或 JSON 文件提供) |
构造时自动:
- 调用
normalize_config()标准化配置(幂等,已标准化的配置原样返回) - 设置输出目录:
src/modules/{app_name} - 初始化 Jinja2 模板环境(
trim_blocks=True,lstrip_blocks=True)
generate() 主方法
def generate(self, auto=False, request=None):
执行流程
1. 校验输出目录不存在(避免覆盖已有模块)
2. 创建输出目录 src/modules/{app_name}/
3. 准备模板上下文数据
4. 渲染后端模板 → 写入 modules 目录
5. 渲染 endpoint 模板 → 写入 api/v1/endpoints/ 目录
6. 渲染前端模板 → 写入 ui/src/views/ 和 ui/src/api/
7. 自动注册到 router.py
8. 自动创建菜单 + 权限节点
参数
| 参数 | 说明 |
|---|---|
auto |
自动模式(当前无交互差异) |
request |
Tornado 请求对象(用于获取操作人信息) |
配置标准化
normalize_config() 将 parser 产出的配置转为模板可用的标准格式:
# parser 产出的字段
{"name": "type", "db_type": "Integer", "comment": "案例类型:1-类型1 2-类型2"}
# 标准化后
{
"name": "type",
"camel_name": "type", # 驼峰命名
"db_type": "Integer",
"form_type": "int", # Pydantic 类型
"comment": "案例类型:1-类型1 2-类型2",
"py_comment": "案例类型:1-类型1 2-类型2", # 转义后
"default_repr": "1", # 默认值表示
"is_status": False, # 状态字段标识
"is_sort": False, # 排序字段标识
}
模板上下文
_prepare_context()
准备后端模板的渲染上下文:
| 变量 | 类型 | 说明 |
|---|---|---|
app_name |
str | 模块名(如 example) |
module_comment |
str | 中文名(如 案例) |
model_class_name |
str | 类名(如 Example) |
permission_prefix |
str | 权限前缀(如 sys:example) |
display_field |
str | 显示字段(如 name) |
has_sort |
bool | 有排序字段 |
has_status |
bool | 有状态字段 |
has_status_route |
bool | 生成状态路由 |
has_image_field |
bool | 有图片字段 |
has_rich_text_field |
bool | 有富文本字段 |
serialize_maps |
dict | 枚举映射 |
sort_field |
str | 排序字段名 |
fields |
list | 全部字段 |
form_fields |
list | 表单字段 |
filter_fields |
list | 精确匹配字段 |
like_fields |
list | 模糊查询字段 |
_prepare_vue_context()
在后端上下文基础上扩展前端专用变量:
| 变量 | 类型 | 说明 |
|---|---|---|
module_name |
str | 驼峰模块名 |
model_class_name_camel |
str | 驼峰类名(首字母小写) |
list_fields |
list | 列表展示字段 |
searchable_fields |
list | 可搜索字段 |
editable_fields |
list | 可编辑字段 |
has_export |
bool | 有导出功能 |
route_prefix |
str | 路由前缀 |
api_path |
str | API 路径 |
is_tree_structure |
bool | 是否树形结构 |
parent_id_field |
str | 父级字段名 |
has_search_form |
bool | 显示搜索表单 |
show_selection |
bool | 显示复选框 |
文件生成
后端文件
| 模板 | 输出路径 | 说明 |
|---|---|---|
__init__.py.tpl |
src/modules/{name}/__init__.py |
模块初始化 |
models.py.tpl |
src/modules/{name}/models.py |
ORM 模型 |
schemas.py.tpl |
src/modules/{name}/schemas.py |
Pydantic 表单 |
repository.py.tpl |
src/modules/{name}/repository.py |
数据访问层 |
service.py.tpl |
src/modules/{name}/service.py |
业务逻辑层 |
endpoint.py.tpl |
src/modules/{name}.py |
HTTP 端点 |
前端文件(普通列表)
| 模板 | 输出路径 |
|---|---|
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 |
前端文件(树状列表)
| 模板 | 输出路径 |
|---|---|
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 |
ui/api.ts.tpl |
ui/src/api/tool/{name}.ts |
树状列表与普通列表共用 api.ts.tpl。
自动注册
路由注册
_register_module() 在 src/api/v1/router.py 中追加:
# 导入语句(插入到最后一个 from api.v1.endpoints 导入之后)
from api.v1.endpoints.example import router as example_router
# 注册语句(追加到文件末尾)
v1._RESOURCE_MODULES 追加(example_router, prefix="/example", tags=["案例"])
幂等操作:如果导入语句已存在,跳过。
菜单创建
_create_menus() 在数据库中创建:
-
二级菜单(type=0):页面路由
- name: 模块中文名
- path:
/tool/{module_camel} - component:
/tool/{module_camel}/index - parent_id: 189(开发工具)
-
三级权限节点(type=1)× 10 个:
| 权限 | 标识 |
|---|---|
| 分页查询 | {prefix}:page |
| 列表查询 | {prefix}:list |
| 详情查询 | {prefix}:detail |
| 新增 | {prefix}:add |
| 编辑 | {prefix}:update |
| 删除 | {prefix}:delete |
| 批量删除 | {prefix}:batchDelete |
| 状态管理 | {prefix}:status |
| 导入 | {prefix}:import |
| 导出 | {prefix}:export |
幂等操作:如果 path 已存在,跳过。创建后自动清除所有用户权限缓存。
总结
代码生成引擎根据数据库表结构和配置信息,通过 Jinja2 模板渲染生成后端(models/schemas/repository/service/endpoint)和前端(index.vue/edit.vue/columns.ts/querySchemas.ts/api.ts)全套代码,生成后自动注册路由和权限。