352 lines
9.4 KiB
Markdown
352 lines
9.4 KiB
Markdown
# 第四章 架构设计 - 扩展性设计
|
||
|
||
## 4.1 扩展性设计原则
|
||
|
||
项目遵循开闭原则(OCP):对扩展开放,对修改关闭。新功能通过添加新模块实现,而非修改现有代码。系统通过 Django App 机制、代码生成器、模板定制等方式提供扩展能力。
|
||
|
||
## 4.2 Django App 机制
|
||
|
||
### 4.2.1 模块化设计
|
||
|
||
每个业务模块独立为一个 Django App,可独立开发、测试和部署:
|
||
|
||
```
|
||
application/
|
||
+-- example/ # 案例模块
|
||
| +-- __init__.py
|
||
| +-- apps.py # 应用配置
|
||
| +-- models.py # 数据模型
|
||
| +-- forms.py # 表单验证
|
||
| +-- services.py # 业务逻辑
|
||
| +-- views.py # 视图处理
|
||
| +-- urls.py # 路由配置
|
||
|
|
||
+-- user/ # 用户模块
|
||
+-- role/ # 角色模块
|
||
+-- ... # 其他模块
|
||
```
|
||
|
||
### 4.2.2 应用注册
|
||
|
||
新模块需要在 `application/settings.py` 中注册:
|
||
|
||
```python
|
||
INSTALLED_APPS = [
|
||
# ... 其他应用
|
||
'application.example', # 注册案例模块
|
||
]
|
||
```
|
||
|
||
### 4.2.3 路由注册
|
||
|
||
新模块需要在 `application/urls.py` 中注册路由:
|
||
|
||
```python
|
||
urlpatterns = [
|
||
# ... 其他路由
|
||
path('example/', include('application.example.urls')),
|
||
]
|
||
```
|
||
|
||
## 4.3 代码生成器
|
||
|
||
### 4.3.1 生成器概述
|
||
|
||
代码生成器是 核心功能,通过数据库表定义自动生成完整的 CRUD 模块,包括:
|
||
|
||
- 后端:Model、Form、Service、View、URL、Admin
|
||
- 前端:Vue 页面、API 模块、表格列配置、查询表单配置
|
||
- 数据库:迁移文件、菜单记录、权限节点
|
||
|
||
### 4.3.2 使用方式
|
||
|
||
```bash
|
||
# 从数据库表生成配置
|
||
python generator.py django_<table>
|
||
|
||
# 从配置文件生成代码
|
||
python generator.py --config config.json
|
||
|
||
# 仅预览配置,不生成代码
|
||
python generator.py django_<table> --dry-run
|
||
```
|
||
|
||
### 4.3.3 生成器工作流程
|
||
|
||
```
|
||
1. 解析数据库表结构
|
||
+-- 获取字段名、类型、注释、长度、索引
|
||
+-- 启发式分类字段(图片、富文本、状态、排序等)
|
||
|
|
||
v
|
||
2. 生成配置文件 (config.json)
|
||
+-- 模块名称、表名、字段定义
|
||
+-- 前端组件类型、验证规则
|
||
|
|
||
v
|
||
3. 渲染 Jinja2 模板
|
||
+-- 后端模板:models.py.tpl, forms.py.tpl, services.py.tpl 等
|
||
+-- 前端模板:index.vue.tpl, edit.vue.tpl, api.ts.tpl 等
|
||
|
|
||
v
|
||
4. 写入文件
|
||
+-- application/<module>/ # 后端模块
|
||
+-- ui/src/views/... # 前端页面
|
||
+-- ui/src/api/... # API模块
|
||
|
|
||
v
|
||
5. 自动注册
|
||
+-- 执行 makemigrations/migrate
|
||
+-- 插入菜单和权限节点
|
||
+-- 追加路由到 application/urls.py
|
||
+-- 追加应用到 INSTALLED_APPS
|
||
```
|
||
|
||
### 4.3.4 配置文件格式
|
||
|
||
```json
|
||
{
|
||
"appName": "example",
|
||
"tableName": "django_example",
|
||
"tableComment": "案例表",
|
||
"className": "Example",
|
||
" moduleName": "案例",
|
||
"fields": [
|
||
{
|
||
"fieldName": "name",
|
||
"fieldType": "CharField",
|
||
"fieldComment": "案例名称",
|
||
"maxLength": 100,
|
||
"isRequired": true,
|
||
"isSearch": true,
|
||
"componentType": "input"
|
||
},
|
||
{
|
||
"fieldName": "status",
|
||
"fieldType": "IntegerField",
|
||
"fieldComment": "案例状态",
|
||
"choices": [
|
||
{"value": 1, "label": "正常"},
|
||
{"value": 2, "label": "禁用"}
|
||
],
|
||
"componentType": "select"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
## 4.4 模板定制
|
||
|
||
### 4.4.1 模板目录
|
||
|
||
代码生成器使用 Jinja2 模板,模板文件位于 `public/templates/` 目录:
|
||
|
||
```
|
||
public/templates/
|
||
+-- models.py.tpl # 模型模板
|
||
+-- forms.py.tpl # 表单模板
|
||
+-- services.py.tpl # 服务模板
|
||
+-- views.py.tpl # 视图模板
|
||
+-- urls.py.tpl # 路由模板
|
||
+-- apps.py.tpl # 应用配置模板
|
||
+-- admin.py.tpl # Admin注册模板
|
||
+-- migration.py.tpl # 迁移文件模板
|
||
+-- ui/
|
||
+-- index.vue.tpl # 列表页模板
|
||
+-- edit.vue.tpl # 编辑页模板
|
||
+-- detail.vue.tpl # 详情页模板
|
||
+-- api.ts.tpl # API模块模板
|
||
+-- columns.ts.tpl # 表格列配置模板
|
||
+-- querySchemas.ts.tpl # 查询表单配置模板
|
||
```
|
||
|
||
### 4.4.2 模板语法示例
|
||
|
||
```jinja
|
||
{# models.py.tpl #}
|
||
from django.db import models
|
||
from application.models import BaseModel
|
||
from utils.common import get_table_name
|
||
|
||
class {{ className }}(BaseModel):
|
||
"""{{ tableComment }}"""
|
||
{% for field in fields %}
|
||
{{ field.fieldName }} = models.{{ field.fieldType }}(
|
||
{% if field.maxLength %} max_length={{ field.maxLength }},{% endif %}
|
||
{% if not field.isRequired %} null=True, blank=True,{% endif %}
|
||
verbose_name="{{ field.fieldComment }}",
|
||
db_comment='{{ field.fieldComment }}'
|
||
)
|
||
{% endfor %}
|
||
|
||
class Meta:
|
||
db_table = get_table_name('{{ appName }}')
|
||
db_table_comment = "{{ tableComment }}"
|
||
```
|
||
|
||
### 4.4.3 自定义模板
|
||
|
||
开发者可以根据项目需求定制模板:
|
||
|
||
1. 修改 `public/templates/` 目录下的模板文件
|
||
2. 使用 Jinja2 语法添加自定义逻辑
|
||
3. 重新运行代码生成器应用新的模板
|
||
|
||
## 4.5 中间件扩展
|
||
|
||
### 4.5.1 自定义中间件
|
||
|
||
通过 Django 中间件机制可灵活添加请求/响应处理逻辑:
|
||
|
||
```python
|
||
# middleware/custom_middleware.py
|
||
class CustomMiddleware:
|
||
"""自定义中间件"""
|
||
|
||
def __init__(self, get_response):
|
||
self.get_response = get_response
|
||
|
||
def __call__(self, request):
|
||
# 请求处理前的逻辑
|
||
# ...
|
||
|
||
response = self.get_response(request)
|
||
|
||
# 响应处理后的逻辑
|
||
# ...
|
||
|
||
return response
|
||
```
|
||
|
||
### 4.5.2 注册中间件
|
||
|
||
在 `application/settings.py` 中注册自定义中间件:
|
||
|
||
```python
|
||
MIDDLEWARE = [
|
||
'corsheaders.middleware.CorsMiddleware',
|
||
'middleware.custom_middleware.CustomMiddleware', # 注册自定义中间件
|
||
# ... 其他中间件
|
||
]
|
||
```
|
||
|
||
## 4.6 信号机制扩展
|
||
|
||
### 4.6.1 Django 信号
|
||
|
||
Django 提供信号机制,可以在特定事件发生时执行自定义逻辑:
|
||
|
||
```python
|
||
from django.db.models.signals import post_save
|
||
from django.dispatch import receiver
|
||
|
||
@receiver(post_save, sender=Example)
|
||
def example_post_save(sender, instance, created, **kwargs):
|
||
"""案例保存后的处理"""
|
||
if created:
|
||
# 新增记录后的逻辑
|
||
pass
|
||
else:
|
||
# 更新记录后的逻辑
|
||
pass
|
||
```
|
||
|
||
### 4.6.2 内置信号
|
||
|
||
| 信号 | 触发时机 | 说明 |
|
||
|------|----------|------|
|
||
| `pre_save` | 保存前 | 数据验证前 |
|
||
| `post_save` | 保存后 | 数据保存后 |
|
||
| `pre_delete` | 删除前 | 删除前检查 |
|
||
| `post_delete` | 删除后 | 清理关联数据 |
|
||
| `class_prepared` | 模型类准备就绪 | 字段顺序重排 |
|
||
|
||
## 4.7 自定义管理命令
|
||
|
||
### 4.7.1 创建管理命令
|
||
|
||
```python
|
||
# application/management/commands/my_command.py
|
||
from django.core.management.base import BaseCommand
|
||
|
||
class Command(BaseCommand):
|
||
help = '自定义管理命令说明'
|
||
|
||
def add_arguments(self, parser):
|
||
parser.add_argument('arg1', type=str, help='参数说明')
|
||
|
||
def handle(self, *args, **options):
|
||
arg1 = options['arg1']
|
||
# 命令逻辑
|
||
self.stdout.write(self.style.SUCCESS(f'执行成功: {arg1}'))
|
||
```
|
||
|
||
### 4.7.2 使用管理命令
|
||
|
||
```bash
|
||
python manage.py my_command value1
|
||
```
|
||
|
||
### 4.7.3 内置管理命令
|
||
|
||
```bash
|
||
python manage.py runserver # 启动开发服务器
|
||
python manage.py makemigrations <app> # 生成迁移文件
|
||
python manage.py migrate # 执行迁移
|
||
python manage.py createsuperuser # 创建超级用户
|
||
```
|
||
|
||
## 4.8 前端扩展
|
||
|
||
### 4.8.1 动态路由
|
||
|
||
前端路由由后端菜单数据动态生成,新页面通过插入菜单记录自动注册:
|
||
|
||
```sql
|
||
INSERT INTO django_menu (name, path, component, permission, type, status)
|
||
VALUES ('案例管理', '/example', 'tool/example/index', 'sys:example:page', 0, 0);
|
||
```
|
||
|
||
### 4.8.2 组件扩展
|
||
|
||
前端使用 Vue3 + NaiveUI,可通过以下方式扩展:
|
||
|
||
1. **自定义组件**:在 `ui/src/components/` 目录下创建新组件
|
||
2. **组合式函数**:在 `ui/src/hooks/` 目录下创建自定义 hooks
|
||
3. **全局指令**:在 `ui/src/directives/` 目录下创建自定义指令
|
||
|
||
### 4.8.3 API 扩展
|
||
|
||
新增 API 接口需要在 `ui/src/api/` 目录下创建对应的 TypeScript 模块:
|
||
|
||
```typescript
|
||
// ui/src/api/tool/example.ts
|
||
import { http } from '@/utils/http/axios'
|
||
|
||
export function getExamplePage(params) {
|
||
return http.get('/example/page', params)
|
||
}
|
||
|
||
export function addExample(data) {
|
||
return http.post('/example/add', data)
|
||
}
|
||
```
|
||
|
||
## 4.9 扩展性最佳实践
|
||
|
||
### 新增模块流程
|
||
|
||
1. **设计数据库表**:确定字段和关联关系
|
||
2. **使用代码生成器**:`python generator.py django_<table>`
|
||
3. **调整生成代码**:根据业务需求修改 Service 层逻辑
|
||
4. **注册菜单权限**:通过管理后台或直接操作数据库
|
||
5. **前端页面定制**:调整 Vue 页面的表格列和表单字段
|
||
|
||
### 扩展注意事项
|
||
|
||
1. **遵循规范**:保持与现有模块一致的代码风格
|
||
2. **软删除**:所有查询都要过滤 `is_delete=False`
|
||
3. **权限节点**:为每个操作定义 `sys:<module>:<action>` 权限
|
||
4. **响应格式**:统一使用 `R.ok()` 和 `R.failed()` 返回响应
|
||
5. **操作日志**:使用 `@operation_log` 装饰器记录操作日志
|