Skip to content

第四章 架构设计 - 扩展性设计

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 + ElementPlus,可通过以下方式扩展:

  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 装饰器记录操作日志

小蚂蚁云团队 · 提供技术支持