Become a sponsor

项目使用 MySQL 8.0 作为主数据库,通过 Django ORM 进行数据访问。所有业务表继承 BaseModel 抽象基类,自动获得 6 个通用字段。
所有业务表继承 BaseModel(application/models.py),自动包含以下字段:
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| 字段 | 类型 | 约束 | 默认值 | 说明 |
|---|---|---|---|---|
id | AutoField | PK, 自增 | - | 主键ID |
create_user | CharField(50) | NULL | None | 创建人用户名 |
create_time | DateTimeField | NULL | auto_now_add | 创建时间,自动填充 |
update_user | CharField(50) | NULL | None | 更新人用户名 |
update_time | DateTimeField | NULL | auto_now | 更新时间,自动刷新 |
is_delete | BooleanField | NOT NULL | 0 | 逻辑删除标识 |
create_time:使用 auto_now_add=True,仅在创建时自动设置当前时间update_time:使用 auto_now=True,每次保存时自动更新为当前时间create_user 和 update_user:需要业务代码手动赋值所有业务表使用统一的前缀,通过 config/env.py 配置:
DATABASE_PREFIX = os.getenv('DATABASE_PREFIX', "django_")使用 get_table_name() 函数自动生成带前缀的表名:
# 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 |
系统采用软删除策略,所有业务表包含 is_delete 字段:
is_delete = 0:正常记录(默认值)is_delete = 1:已删除记录# 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}条数据")所有查询都需要过滤已删除的记录:
# 分页查询
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)| 优势 | 说明 |
|---|---|
| 数据可恢复 | 误删除的数据可以恢复 |
| 审计追踪 | 保留删除记录的历史 |
| 关联完整 | 不破坏外键关联关系 |
| 操作安全 | 避免物理删除造成的数据丢失 |
通过 Django 的 class_prepared 信号,自动将 BaseModel 的公共字段移到业务字段之后,使数据库表结构更清晰。
# 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_deleteCREATE 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='案例表';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='用户表';| Django 字段 | MySQL 类型 | 说明 |
|---|---|---|
AutoField | INT AUTO_INCREMENT | 自增主键 |
CharField | VARCHAR(n) | 变长字符串 |
TextField | LONGTEXT | 长文本 |
IntegerField | INT | 整数 |
BooleanField | TINYINT(1) | 布尔值 |
DateTimeField | DATETIME(6) | 日期时间 |
DecimalField | DECIMAL(p,s) | 精确小数 |
ImageField | VARCHAR(255) | 图片路径 |
ForeignKey | INT + 外键约束 | 外键关联 |
id 自动创建主键索引在模型定义中使用 db_index=True 为常用查询字段创建索引:
name = models.CharField(
max_length=100,
db_index=True, # 创建索引
verbose_name="案例名称"
)idx_<表名>_<字段名>示例:idx_example_name、idx_user_username
python manage.py makemigrations <app_name>python manage.py migrate代码生成器在生成新模块时会自动执行迁移:
# generator_config.py
os.system('python manage.py makemigrations')
os.system('python manage.py migrate')