签入版本

This commit is contained in:
2026-09-12 23:12:15 +08:00
commit 91998056ca
1841 changed files with 341325 additions and 0 deletions
@@ -0,0 +1,252 @@
# Model层规范
## 概述
Model 层负责定义数据库表结构,所有业务模型继承 `BaseModel` 抽象基类,自动获得公共字段(id、create_user、create_time、update_user、update_time、is_delete)。
:::tip 设计原则
- 所有模型继承 `BaseModel`
- 字段命名使用 snake_case
- 每个字段必须有 `db_comment` 注释
- 使用 `get_table_name()` 生成表名
:::
## BaseModel 基类
`application/models.py` 定义了 `BaseModel` 抽象基类:
```python
from django.db import models
class BaseModel(models.Model):
"""基础模型抽象类"""
# 主键ID字段
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,
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,
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
```
## 完整示例
以案例模块为例,`application/example/models.py`:
```python
from django.db import models
from application.models import BaseModel
from utils.common import get_table_name
class Example(BaseModel):
"""案例模型类"""
# 案例名称
name = models.CharField(
null=False, max_length=100, db_index=True,
verbose_name="案例名称",
help_text="案例名称",
db_comment='案例名称'
)
# 案例图片
avatar = models.CharField(
null=True, blank=True, max_length=255,
verbose_name="案例图片",
help_text="案例图片",
db_comment='案例图片'
)
# 案例类型
TYPE_CHOICES = (
(1, "类型1"),
(2, "类型2"),
(3, "类型3"),
(4, "类型4"),
)
type = models.IntegerField(
null=False, choices=TYPE_CHOICES,
verbose_name="案例类型:1-类型1 2-类型2 3-类型3 4-类型4",
help_text="案例类型:1-类型1 2-类型2 3-类型3 4-类型4",
db_comment='案例类型:1-类型1 2-类型2 3-类型3 4-类型4'
)
# 案例状态
STATUS_CHOICES = (
(1, "正常"),
(2, "禁用"),
)
status = models.IntegerField(
null=False, choices=STATUS_CHOICES,
verbose_name="案例状态:1-正常 2-禁用",
help_text="案例状态:1-正常 2-禁用",
db_comment='案例状态:1-正常 2-禁用'
)
# 排序
sort = models.IntegerField(
null=False,
verbose_name="排序",
help_text="排序",
db_comment='排序'
)
class Meta:
db_table = get_table_name('example')
db_table_comment = "案例表"
verbose_name = "案例表"
verbose_name_plural = verbose_name
ordering = ("sort",)
def __str__(self):
return f"案例{self.name}"
```
## 字段定义规范
### 字段类型映射
| 数据库类型 | Django 字段类型 | 说明 |
|:----|:----|:----|
| varchar | CharField | 短文本,需指定 max_length |
| text | TextField | 长文本 |
| int | IntegerField | 整数 |
| datetime | DateTimeField | 日期时间 |
| date | DateField | 日期 |
| float | FloatField | 浮点数 |
| decimal | DecimalField | 精确小数 |
| boolean | BooleanField | 布尔值 |
### 字段属性
| 属性 | 说明 | 示例 |
|:----|:----|:----|
| `null` | 数据库是否允许 NULL | `null=True` |
| `blank` | 表单验证是否允许空 | `blank=True` |
| `max_length` | 最大长度 | `max_length=100` |
| `default` | 默认值 | `default=0` |
| `db_index` | 是否创建索引 | `db_index=True` |
| `choices` | 选项列表 | `choices=STATUS_CHOICES` |
| `verbose_name` | 字段中文名 | `verbose_name="案例名称"` |
| `help_text` | 帮助文本 | `help_text="案例名称"` |
| `db_comment` | 数据库字段注释 | `db_comment='案例名称'` |
### 选项字段定义
```python
# 状态字段
STATUS_CHOICES = (
(1, "正常"), # 正常状态
(2, "禁用"), # 禁用状态
)
status = models.IntegerField(
null=False, choices=STATUS_CHOICES,
verbose_name="状态:1-正常 2-禁用",
db_comment='状态:1-正常 2-禁用'
)
```
:::tip 选项定义约定
- 选项定义为类属性,命名为 `{FIELD}_CHOICES`
- 选项格式为 `(value, label)` 元组
- 字段注释中包含选项说明(如 `1-正常 2-禁用`)
:::
## Meta 类配置
```python
class Meta:
# 数据表名(使用 get_table_name 自动生成)
db_table = get_table_name('example')
# 表注释(Django 4.1+)
db_table_comment = "案例表"
# Admin 后台显示名称
verbose_name = "案例表"
verbose_name_plural = verbose_name
# 默认排序
ordering = ("sort",)
```
### get_table_name 函数
`utils/common.py` 中的 `get_table_name` 函数自动拼接表前缀:
```python
from config.env import DATABASE_PREFIX
def get_table_name(table_name):
"""获取带前缀的表名"""
return f"{DATABASE_PREFIX}{table_name}"
```
例如:`DATABASE_PREFIX = "django_"` 时,`get_table_name('example')` 返回 `"django_example"`。
## 索引定义
```python
class Example(BaseModel):
name = models.CharField(max_length=100, db_index=True) # 单列索引
class Meta:
indexes = [
models.Index(fields=['status', 'type'], name='idx_status_type'), # 复合索引
]
```
## 信号机制
项目使用 `class_prepared` 信号自动重排字段顺序,将公共字段(id、create_user 等)移到业务字段之后:
```python
from django.db.models.signals import class_prepared
def _reorder_fields(sender, **kwargs):
"""重排模型字段顺序,将公共字段移到最后"""
# ... 实现逻辑 ...
class_prepared.connect(_reorder_fields)
```
## 总结
Model 层通过继承 `BaseModel` 获得公共字段,使用 `get_table_name()` 生成带前缀的表名。字段定义需包含 `db_comment` 注释、`verbose_name` 中文名。选项字段使用 `choices` 参数定义,排序使用 `Meta.ordering` 配置。