229 lines
6.7 KiB
Markdown
229 lines
6.7 KiB
Markdown
# 数据库设计指南
|
||
|
||
:::tip 说明
|
||
本文介绍本项目的数据库设计规范,包括表命名、字段类型选择、索引策略、常见表模式等。
|
||
:::
|
||
|
||
## 表命名规范
|
||
|
||
| 规则 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| 前缀 | 统一使用 `django_` 前缀 | `django_user` |
|
||
| 命名 | 小写字母 + 下划线 | `django_role_menu` |
|
||
| 关联表 | 两张表名拼接 | `django_user_role` |
|
||
| 日志表 | 模块名 + `_log` | `django_login_log` |
|
||
|
||
### Django 模型配置
|
||
|
||
```python
|
||
class Example(BaseModel):
|
||
class Meta:
|
||
db_table = 'django_example' # 表名
|
||
db_comment = '案例表' # 表注释
|
||
```
|
||
|
||
## 字段类型选择
|
||
|
||
### 常用字段类型
|
||
|
||
| Django 类型 | MySQL 类型 | 适用场景 | 示例 |
|
||
|------------|-----------|---------|------|
|
||
| `AutoField` | INT AUTO_INCREMENT | 主键 | `id` |
|
||
| `CharField` | VARCHAR | 短文本 | 用户名、标题 |
|
||
| `TextField` | TEXT | 长文本 | 文章内容、备注 |
|
||
| `IntegerField` | INT | 整数 | 状态、排序、数量 |
|
||
| `BigIntegerField` | BIGINT | 大整数 | 时间戳、耗时 |
|
||
| `DecimalField` | DECIMAL | 精确小数 | 金额、价格 |
|
||
| `DateTimeField` | DATETIME | 日期时间 | 创建时间、更新时间 |
|
||
| `BooleanField` | TINYINT | 布尔值 | 是否启用 |
|
||
|
||
### 字段长度建议
|
||
|
||
| 字段类型 | 建议长度 | 说明 |
|
||
|---------|---------|------|
|
||
| 用户名 | 50 | `CharField(max_length=50)` |
|
||
| 标题 | 150-255 | `CharField(max_length=150)` |
|
||
| URL/路径 | 255 | `CharField(max_length=255)` |
|
||
| 编码/标识 | 100 | `CharField(max_length=100)` |
|
||
| 手机号 | 20 | `CharField(max_length=20)` |
|
||
| 邮箱 | 100 | `CharField(max_length=100)` |
|
||
| 备注 | 255 | `CharField(max_length=255)` |
|
||
| 内容 | 无限制 | `TextField()` |
|
||
|
||
## BaseModel 公共字段
|
||
|
||
所有业务模型继承 `BaseModel`,自动包含 6 个公共字段:
|
||
|
||
```python
|
||
# application/models.py
|
||
class BaseModel(models.Model):
|
||
"""基础模型类"""
|
||
class Meta:
|
||
abstract = True
|
||
|
||
id = models.AutoField(primary_key=True, verbose_name='主键ID')
|
||
create_user = models.CharField(max_length=50, null=True, blank=True, verbose_name='创建人')
|
||
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
||
update_user = models.CharField(max_length=50, null=True, blank=True, verbose_name='更新人')
|
||
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
|
||
is_delete = models.IntegerField(default=0, verbose_name='是否删除:0-正常 1-已删除')
|
||
```
|
||
|
||
:::tip 字段排序
|
||
通过 `class_prepared` 信号,BaseModel 的公共字段会自动排在业务字段之后,保证数据库表结构的可读性。
|
||
:::
|
||
|
||
## 索引设计原则
|
||
|
||
### 索引类型
|
||
|
||
| 类型 | Django 配置 | 说明 |
|
||
|------|------------|------|
|
||
| 单列索引 | `db_index=True` | 单字段查询 |
|
||
| 唯一索引 | `unique=True` | 唯一性约束 |
|
||
| 复合索引 | `index_together` | 多字段联合查询 |
|
||
|
||
### 索引设计建议
|
||
|
||
```python
|
||
class Example(BaseModel):
|
||
name = models.CharField(max_length=100, db_index=True) # 常用查询字段
|
||
code = models.CharField(max_length=100, unique=True) # 唯一编码
|
||
status = models.IntegerField(db_index=True) # 状态字段
|
||
category_id = models.IntegerField(db_index=True) # 外键字段
|
||
|
||
class Meta:
|
||
db_table = 'django_example'
|
||
index_together = [
|
||
['status', 'is_delete'], # 复合索引:状态 + 软删除
|
||
['category_id', 'sort'], # 复合索引:分类 + 排序
|
||
]
|
||
```
|
||
|
||
### 索引注意事项
|
||
|
||
```
|
||
1. 不要过度索引:每个索引都会降低写入性能
|
||
2. 选择性高的字段优先:username 比 status 选择性更高
|
||
3. 复合索引顺序:选择性高的字段放前面
|
||
4. 覆盖索引:查询字段都在索引中时,无需回表
|
||
5. 定期分析:使用 EXPLAIN 分析慢查询
|
||
```
|
||
|
||
## 常见表模式
|
||
|
||
### 树形结构表
|
||
|
||
```python
|
||
class Category(BaseModel):
|
||
"""树形结构表(parent_id)"""
|
||
name = models.CharField(max_length=100)
|
||
parent_id = models.IntegerField(default=0) # 0 表示顶级
|
||
sort = models.IntegerField(default=0)
|
||
|
||
class Meta:
|
||
db_table = 'django_category'
|
||
```
|
||
|
||
### 关联表(多对多)
|
||
|
||
```python
|
||
class RoleMenu(BaseModel):
|
||
"""角色菜单关联表"""
|
||
role_id = models.IntegerField(db_index=True)
|
||
menu_id = models.IntegerField(db_index=True)
|
||
|
||
class Meta:
|
||
db_table = 'django_role_menu'
|
||
```
|
||
|
||
### 配置表(KV 结构)
|
||
|
||
```python
|
||
class ConfigItem(BaseModel):
|
||
"""配置项表(键值对)"""
|
||
code = models.CharField(max_length=100, unique=True) # 配置编码
|
||
value = models.CharField(max_length=1000) # 配置值
|
||
type = models.CharField(max_length=50) # 值类型
|
||
|
||
class Meta:
|
||
db_table = 'django_config_item'
|
||
```
|
||
|
||
### 日志表
|
||
|
||
```python
|
||
class LoginLog(BaseModel):
|
||
"""登录日志表"""
|
||
username = models.CharField(max_length=50, db_index=True)
|
||
ip = models.CharField(max_length=50)
|
||
status = models.IntegerField(default=0)
|
||
log_type = models.IntegerField(default=1)
|
||
|
||
class Meta:
|
||
db_table = 'django_login_log'
|
||
```
|
||
|
||
## 数据库迁移最佳实践
|
||
|
||
### 创建迁移
|
||
|
||
```bash
|
||
# 为指定应用创建迁移
|
||
python manage.py makemigrations example
|
||
|
||
# 为所有应用创建迁移
|
||
python manage.py makemigrations
|
||
```
|
||
|
||
### 执行迁移
|
||
|
||
```bash
|
||
# 执行所有未执行的迁移
|
||
python manage.py migrate
|
||
|
||
# 执行指定应用的迁移
|
||
python manage.py migrate example
|
||
|
||
# 回滚到指定迁移
|
||
python manage.py migrate example 0001
|
||
```
|
||
|
||
### 迁移注意事项
|
||
|
||
```
|
||
1. 先备份:生产环境执行迁移前先备份数据库
|
||
2. 测试环境验证:先在测试环境验证迁移脚本
|
||
3. 分批执行:大数据表的迁移分批执行,避免锁表
|
||
4. 不要修改已提交的迁移:已提交到 Git 的迁移文件不要修改
|
||
5. 生成迁移后检查:检查生成的迁移文件是否符合预期
|
||
```
|
||
|
||
## 多数据库支持
|
||
|
||
项目通过 `DATABASE_ENGINE` 环境变量支持多种数据库:
|
||
|
||
```bash
|
||
# .env
|
||
# 可选值:mysql / postgresql / sqlite / oracle / sqlserver
|
||
DATABASE_ENGINE=mysql
|
||
DATABASE_NAME=djangoadmin
|
||
DATABASE_HOST=127.0.0.1
|
||
DATABASE_PORT=3306
|
||
DATABASE_USER=root
|
||
DATABASE_PASSWORD=root
|
||
```
|
||
|
||
### 数据库方言差异
|
||
|
||
| 特性 | MySQL | PostgreSQL | SQLite |
|
||
|------|-------|-----------|--------|
|
||
| 自增主键 | AUTO_INCREMENT | SERIAL | AUTOINCREMENT |
|
||
| 布尔类型 | TINYINT | BOOLEAN | INTEGER |
|
||
| JSON 字段 | JSON | JSONB | TEXT |
|
||
| 全文索引 | FULLTEXT | GIN/GiST | FTS5 |
|
||
|
||
## 总结
|
||
|
||
数据库设计指南涵盖表命名规范、字段类型选择、索引设计、常见表模式、迁移最佳实践、多数据库支持等方面。核心原则:统一命名、合理索引、软删除、公共字段复用。
|