Files
djangoadmin-wiki/DjangoAdmin_Flask_NaiveVue/zh/volume5/demo.md
T
2026-09-12 23:12:15 +08:00

403 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:::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.response import R
from src.common.utils.request import parse_request_body, parse_id_list
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+ 行代码,涵盖后端三层 + 前端页面 + 路由注册 + 菜单权限。生成后根据业务需求进行微调即可投入使用。