Skip to content

第四章 架构设计 - 数据库设计

4.1 数据库设计概述

项目使用 MySQL 8.0 作为主数据库,通过 Django ORM 进行数据访问。所有业务表继承 BaseModel 抽象基类,自动获得 6 个通用字段。

4.2 通用字段规范

BaseModel 字段定义

所有业务表继承 BaseModelapplication/models.py),自动包含以下字段:

python
class BaseModel(models.Model):
    """基础模型抽象类"""

    id = models.AutoField(
        auto_created=True, primary_key=True, serialize=False,
        verbose_name='主键ID', db_comment='主键ID'
    )

    create_user = models.CharField(
        null=True, max_length=50, default=None, db_default=None,
        verbose_name='创建人', db_comment='创建人'
    )

    create_time = models.DateTimeField(
        null=True, auto_now_add=True,
        verbose_name="创建时间", db_comment='创建时间'
    )

    update_user = models.CharField(
        null=True, max_length=50, default=None, db_default=None,
        verbose_name='更新人', db_comment='更新人'
    )

    update_time = models.DateTimeField(
        null=True, auto_now=True,
        verbose_name="更新时间", db_comment='更新时间'
    )

    is_delete = models.BooleanField(
        default=0, db_default=0,
        verbose_name="逻辑删除",
        db_comment='逻辑删除:0-正常 1-已删除'
    )

    class Meta:
        abstract = True

字段说明

字段类型约束默认值说明
idAutoFieldPK, 自增-主键ID
create_userCharField(50)NULLNone创建人用户名
create_timeDateTimeFieldNULLauto_now_add创建时间,自动填充
update_userCharField(50)NULLNone更新人用户名
update_timeDateTimeFieldNULLauto_now更新时间,自动刷新
is_deleteBooleanFieldNOT NULL0逻辑删除标识

字段自动管理

  • create_time:使用 auto_now_add=True,仅在创建时自动设置当前时间
  • update_time:使用 auto_now=True,每次保存时自动更新为当前时间
  • create_userupdate_user:需要业务代码手动赋值

4.3 表名命名规范

表前缀配置

所有业务表使用统一的前缀,通过 config/env.py 配置:

python
DATABASE_PREFIX = os.getenv('DATABASE_PREFIX', "django_")

表名生成函数

使用 get_table_name() 函数自动生成带前缀的表名:

python
# utils/common.py
def get_table_name(name):
    """获取带前缀的表名"""
    from config.env import DATABASE_PREFIX
    return f"{DATABASE_PREFIX}{name}"

表名示例

模块配置的表名实际表名
案例get_table_name('example')django_example
用户get_table_name('user')django_user
角色get_table_name('role')django_role
菜单get_table_name('menu')django_menu
部门get_table_name('dept')django_dept
字典get_table_name('dict')django_dict

4.4 软删除设计

设计原理

系统采用软删除策略,所有业务表包含 is_delete 字段:

  • is_delete = 0:正常记录(默认值)
  • is_delete = 1:已删除记录

软删除实现

python
# Service层删除操作
def delete_examples(instance_ids):
    """删除案例(批量删除)"""
    id_list = [int(id_str.strip())
               for id_str in instance_ids.split(',') if id_str.strip()]

    # 批量更新删除标识(逻辑删除)
    updated_count = Example.objects.filter(
        id__in=id_list, is_delete=False
    ).update(is_delete=True)

    return R.ok(msg=f"本次共删除{updated_count}条数据")

查询过滤

所有查询都需要过滤已删除的记录:

python
# 分页查询
query = Example.objects.filter(is_delete=False)

# 详情查询
instance = Example.objects.filter(id=id, is_delete=False).first()

# 列表查询
queryset = Example.objects.filter(is_delete=False, status=1)

软删除优势

优势说明
数据可恢复误删除的数据可以恢复
审计追踪保留删除记录的历史
关联完整不破坏外键关联关系
操作安全避免物理删除造成的数据丢失

4.5 字段顺序重排

设计目标

通过 Django 的 class_prepared 信号,自动将 BaseModel 的公共字段移到业务字段之后,使数据库表结构更清晰。

实现代码

python
# application/models.py
BASE_FIELD_NAMES = ['id', 'create_user', 'create_time',
                    'update_user', 'update_time', 'is_delete']

def _reorder_fields(sender, **kwargs):
    """信号处理函数:重排模型字段顺序"""
    if not hasattr(sender, '_meta') or sender._meta.abstract:
        return

    # 检查是否有公共字段
    has_base_fields = any(
        f.name in BASE_FIELD_NAMES for f in sender._meta.local_fields
    )
    if not has_base_fields:
        return

    # 分离公共字段和业务字段
    base_fields = []
    business_fields = []

    for field in sender._meta.local_fields:
        if field.name in BASE_FIELD_NAMES:
            base_fields.append(field)
        else:
            business_fields.append(field)

    # 重新排列:业务字段在前,公共字段在后
    sender._meta.local_fields = business_fields + base_fields

# 注册信号处理器
class_prepared.connect(_reorder_fields)

重排效果

重排前:id, create_user, create_time, name, status, sort, update_user, update_time, is_delete
重排后:name, status, sort, id, create_user, create_time, update_user, update_time, is_delete

4.6 数据库表结构示例

案例表 (django_example)

sql
CREATE TABLE `django_example` (
  `name` varchar(100) NOT NULL COMMENT '案例名称',
  `avatar` varchar(255) DEFAULT NULL COMMENT '案例图片',
  `type` int NOT NULL COMMENT '案例类型:1-类型1 2-类型2 3-类型3 4-类型4',
  `status` int NOT NULL COMMENT '案例状态:1-正常 2-禁用',
  `sort` int NOT NULL COMMENT '排序',
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `create_user` varchar(50) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime(6) DEFAULT NULL COMMENT '创建时间',
  `update_user` varchar(50) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime(6) DEFAULT NULL COMMENT '更新时间',
  `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除:0-正常 1-已删除',
  PRIMARY KEY (`id`),
  KEY `idx_example_name` (`name`)
) ENGINE=InnoDB COMMENT='案例表';

用户表 (django_user)

sql
CREATE TABLE `django_user` (
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(128) NOT NULL COMMENT '密码',
  `realname` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `phone` varchar(20) DEFAULT NULL COMMENT '手机号',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `avatar` varchar(255) DEFAULT NULL COMMENT '头像',
  `status` int NOT NULL DEFAULT 1 COMMENT '状态:1-正常 2-禁用',
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `create_user` varchar(50) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime(6) DEFAULT NULL COMMENT '创建时间',
  `update_user` varchar(50) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime(6) DEFAULT NULL COMMENT '更新时间',
  `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除:0-正常 1-已删除',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_user_username` (`username`)
) ENGINE=InnoDB COMMENT='用户表';

4.7 字段类型映射

Django 字段MySQL 类型说明
AutoFieldINT AUTO_INCREMENT自增主键
CharFieldVARCHAR(n)变长字符串
TextFieldLONGTEXT长文本
IntegerFieldINT整数
BooleanFieldTINYINT(1)布尔值
DateTimeFieldDATETIME(6)日期时间
DecimalFieldDECIMAL(p,s)精确小数
ImageFieldVARCHAR(255)图片路径
ForeignKeyINT + 外键约束外键关联

4.8 索引设计规范

自动索引

  • 主键 id 自动创建主键索引
  • 唯一约束字段自动创建唯一索引

手动索引

在模型定义中使用 db_index=True 为常用查询字段创建索引:

python
name = models.CharField(
    max_length=100,
    db_index=True,  # 创建索引
    verbose_name="案例名称"
)

索引命名规范

idx_<表名>_<字段名>

示例:idx_example_nameidx_user_username

4.9 数据库迁移

生成迁移文件

bash
python manage.py makemigrations <app_name>

执行迁移

bash
python manage.py migrate

代码生成器自动迁移

代码生成器在生成新模块时会自动执行迁移:

python
# generator_config.py
os.system('python manage.py makemigrations')
os.system('python manage.py migrate')

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