:::tip 本章概要 以 flask_example 演示表为完整案例,演示从建表到生成到使用的全流程。 ::: # 实战案例 以 `flask_example` 演示表为完整案例,演示从建表到生成到使用的全流程。 ## 第 1 步:创建数据表 在数据库中执行建表语句: ```sql CREATE TABLE `flask_example` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL COMMENT '案例名称', `code` varchar(50) NOT NULL COMMENT '案例编码', `type` int DEFAULT 1 COMMENT '案例类型:1-类型1 2-类型2 3-类型3', `status` int DEFAULT 1 COMMENT '案例状态:1-正常 2-停用', `sort` int DEFAULT 0 COMMENT '排序', `cover` varchar(255) DEFAULT NULL COMMENT '封面图', `content` text COMMENT '案例内容', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `create_user` varchar(50) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `update_user` varchar(50) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `is_delete` int DEFAULT 0, PRIMARY KEY (`id`) ) COMMENT='案例表'; ``` ## 第 2 步:预览配置 ```bash python generator.py flask_example --dry-run ``` 输出: ``` ============================================================== 数据库表结构解析和代码生成工具 ============================================================== 正在解析表: flask_example 表结构解析成功 ------------------------------------------------------------ 生成配置摘要: ------------------------------------------------------------ 应用名称: example 模块名称: 案例 模型类名: Example 字段数量: 8 是否有排序: True 是否有状态: True - name: 案例名称 (String) - code: 案例编码 (String) - type: 案例类型 (Integer) 选项: [(1, '类型1'), (2, '类型2'), (3, '类型3')] - status: 案例状态 (Integer) 选项: [(1, '正常'), (2, '停用')] - sort: 排序 (Integer) ... 还有 3 个字段 ============================================================== 预览模式 - 不执行代码生成(去掉 --dry-run 参数即可生成) ============================================================== ``` ## 第 3 步:生成代码 ```bash python generator.py flask_example ``` 输出: ``` ============================================================== 数据库表结构解析和代码生成工具 ============================================================== 正在解析表: flask_example 表结构解析成功 ... 创建输出目录: src/modules/example 生成文件: src/modules/example/__init__.py 生成文件: src/modules/example/models.py 生成文件: src/modules/example/schema.py 生成文件: src/modules/example/repository.py 生成文件: src/modules/example/service.py 生成文件: src/modules/example/router.py 生成文件: ui/src/views/tool/example/index.vue 生成文件: ui/src/views/tool/example/edit.vue 生成文件: ui/src/views/tool/example/detail.vue 生成文件: ui/src/views/tool/example/querySchemas.ts 生成文件: ui/src/views/tool/example/columns.ts 生成文件: ui/src/api/tool/example.ts 已更新路由注册: src/routes/v1.py 已自动创建菜单: 案例(10 个权限节点) 代码生成完成! ``` ## 第 4 步:验证生成结果 ### 检查后端文件 ```bash ls src/modules/example/ # __init__.py models.py repository.py schema.py service.py router.py ``` ### 检查前端文件 ```bash ls ui/src/views/tool/example/ # index.vue edit.vue detail.vue columns.ts querySchemas.ts ls ui/src/api/tool/example.ts # example.ts ``` ### 检查路由注册 在 `src/routes/v1.py` 中应新增: ```python from src.modules.example.router import example_blue BLUEPRINTS = [ # ... 其他模块 example_blue, ] ``` ## 第 5 步:重启后端 ```bash python app.py ``` ## 第 6 步:访问页面 1. 登录管理后台 2. 左侧菜单找到「开发工具 → 案例」 3. 进入案例管理页面,测试增删改查功能 ![](/volume5/4.png) ## 生成代码逐文件解析 ### models.py ```python from src.common.base_db import BaseDB from src.common.base_model import BaseModel from config.database import DB_PREFIX class Example(BaseModel, BaseDB): __tablename__ = DB_PREFIX + "example" name = Column(String(100), nullable=False, comment="案例名称") code = Column(String(50), nullable=False, comment="案例编码") type = Column(Integer, default=1, comment="案例类型:1-类型1 2-类型2 3-类型3") status = Column(Integer, default=1, comment="案例状态:1-正常 2-停用") sort = Column(Integer, default=0, comment="排序") cover = Column(String(255), nullable=True, comment="封面图") content = Column(Text, nullable=True, comment="案例内容") remark = Column(String(500), nullable=True, comment="备注") ``` - 自动映射字段类型(varchar→String, int→Integer, text→Text) - 自动识别 `cover` 为图片字段 - 自动识别 `content` 为富文本字段(注释含"内容"关键词) - 系统字段(id/create_user/create_time 等)由基类提供,不重复定义 ### schema.py ```python from wtforms import StringField, IntegerField from wtforms.validators import DataRequired, Length, NumberRange, Optional from src.common.forms.base_form import BaseForm class ExampleForm(BaseForm): name = StringField('案例名称', validators=[ DataRequired(message='案例名称不能为空'), Length(min=1, max=100, message='案例名称长度必须在1-100个字符之间') ]) code = StringField('案例编码', validators=[ DataRequired(message='案例编码不能为空'), Length(min=1, max=50, message='案例编码长度必须在1-50个字符之间') ]) type = IntegerField('案例类型', validators=[ DataRequired(message='案例类型不能为空'), NumberRange(min=1, max=3, message='案例类型必须是1-3') ]) status = IntegerField('案例状态', validators=[ DataRequired(message='案例状态不能为空'), NumberRange(min=1, max=2, message='案例状态必须是1或2') ]) sort = IntegerField('排序', validators=[ DataRequired(message='排序不能为空'), NumberRange(min=0, max=99999, message='排序必须在0-99999之间') ]) cover = StringField('封面图', validators=[Optional()]) content = StringField('案例内容', validators=[Optional()]) remark = StringField('备注', validators=[Optional()]) class ExampleStatusForm(BaseForm): id = IntegerField('案例ID', validators=[ DataRequired(message='案例ID不能为空'), NumberRange(min=1, message='案例ID必须大于0') ]) status = IntegerField('案例状态', validators=[ DataRequired(message='案例状态不能为空'), NumberRange(min=1, max=2, message='案例状态必须是1或2') ]) ``` - `name`/`code`/`type`/`status`/`sort` 为必填 - `cover`/`content`/`remark` 为可选 - 自动生成 `StatusForm`(因为有 `status` 字段) ### service.py ```python from src.common.base_service import BaseService from src.modules.example.models import Example from src.modules.example.repository import ExampleRepository class ExampleService(BaseService): repository = ExampleRepository form = ExampleForm status_form = ExampleStatusForm model_name = "示例" serialize_maps = {'type': 'example_type', 'status': 'example_status'} get_example_page = _example_service.get_page get_example_detail = _example_service.get_detail add_example = _example_service.add update_example = _example_service.update delete_example = _example_service.delete batch_delete_examples = _example_service.batch_delete update_example_status = _example_service.update_status ``` - `name`/`code`/`remark` 为模糊查询字段(字符串类型) - `type`/`status` 为精确匹配字段(有选项) - 默认按 `sort` 升序、`id` 降序排列 - `cover` 标记为文件字段(自动处理上传和 URL) - `serialize_maps` 自动关联数据字典 ### router.py ```python from flask import Blueprint, request from src.core.permission import check_permission from src.core import response as R from src.common.utils.request import parse_request_body, parse_batch_ids example_blue = Blueprint('example', __name__, url_prefix='/example') @example_blue.route('/page', methods=['GET']) @check_permission('sys:example:page') def page(): from src.modules.example.service import get_example_page return get_example_page() @example_blue.route('/add', methods=['POST']) @check_permission('sys:example:add') def add(): from src.modules.example.service import add_example from src.modules.example.schema import ExampleForm data = parse_request_body(request, ExampleForm) return add_example(data) # ... update / delete / batchDelete / status / detail / list ``` - 自动生成 8 个端点(page/detail/list/add/update/delete/batchDelete/status) - 写操作自动加 `@check_permission` 装饰器 ## 批量生成示例 创建第二张表: ```sql CREATE TABLE `flask_product` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(200) NOT NULL COMMENT '商品名称', `price` decimal(10,2) DEFAULT 0 COMMENT '价格', `stock` int DEFAULT 0 COMMENT '库存', `status` int DEFAULT 1 COMMENT '状态:1-上架 2-下架', `sort` int DEFAULT 0 COMMENT '排序', `create_user` varchar(50) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `update_user` varchar(50) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `is_delete` int DEFAULT 0, PRIMARY KEY (`id`) ) COMMENT='商品表'; ``` Web 界面批量生成: ![](/volume5/3.png) ```json { "tableNames": [ "flask_example|案例表", "flask_product|商品表" ] } ``` CLI 循环生成: ```bash python generator.py flask_example python generator.py flask_product ``` ## 树状表示例 当表中包含 `parent_id` 或 `pid` 字段时,生成器自动切换为树状模板。 ### 创建树状表 ```sql CREATE TABLE `flask_category` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL COMMENT '分类名称', `parent_id` int DEFAULT 0 COMMENT '父级ID(0为顶级)', `sort` int DEFAULT 0 COMMENT '排序', `status` int DEFAULT 1 COMMENT '状态:1-正常 2-停用', `create_user` varchar(50) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `update_user` varchar(50) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `is_delete` int DEFAULT 0, PRIMARY KEY (`id`) ) COMMENT='分类表'; ``` ### 生成结果差异 因为表中包含 `parent_id` 字段,生成器自动: 1. **前端模板切换**:使用 `ui2/` 树形模板替代 `ui/` 普通列表模板 2. **生成文件减少**:不生成 `columns.ts` 和 `querySchemas.ts`(树形组件内联列定义) 3. **数据加载方式**:全量加载 + 前端 `buildTree` 构建树形结构 4. **交互差异**:支持展开/折叠、父子级联选择 ``` 普通列表(ui/) 树状列表(ui2/) ├── index.vue ├── index.vue(内联列 + buildTree) ├── edit.vue ├── edit.vue(含父级选择) ├── detail.vue ├── detail.vue ├── columns.ts └── (无 columns.ts) ├── querySchemas.ts └── (无 querySchemas.ts) └── api.ts └── api.ts(共用) ``` ## 生成后的自定义 代码生成后,通常需要根据业务需求进行微调: ### 常见自定义项 | 自定义项 | 涉及文件 | 说明 | |:----|:----|:----| | 添加业务校验 | `schema.py` | 添加 `validate_` 自定义校验逻辑 | | 添加删除前检查 | `service.py` | 覆盖 `before_delete` 钩子 | | 添加创建前处理 | `service.py` | 覆盖 `before_add` 钩子(如密码哈希) | | 修改序列化 | `service.py` | 覆盖 `_detail_dict` / `_enrich_page_records` 钩子 | | 添加自定义接口 | `router.py` | 新增路由方法 | | 调整前端布局 | `index.vue` | 修改表格列宽、操作按钮等 | | 调整表单校验 | `edit.vue` | 修改表单规则、默认值等 | ### 示例:添加删除前检查 ```python # src/modules/example/service.py class ExampleService(BaseService): # ... 原有配置 ... @classmethod def before_delete(cls, ids): """删除前校验:检查是否有关联数据""" for eid in ids: if cls.repository.count_children(eid) > 0: raise BizError("存在子分类,请先删除子分类") ``` ## 总结 通过以上 6 步即可完成一个完整业务模块的生成: 1. 建表 → 2. 预览 → 3. 生成 → 4. 验证 → 5. 重启 → 6. 使用 整个过程约 1 分钟,生成约 12 个文件、500+ 行代码,涵盖后端三层 + 前端页面 + 路由注册 + 菜单权限。生成后根据业务需求进行微调即可投入使用。