签入版本
This commit is contained in:
@@ -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` 配置。
|
||||
Reference in New Issue
Block a user