Skip to content

Model层规范

概述

Model 层负责定义数据库表结构,所有业务模型继承 BaseModel 抽象基类,自动获得公共字段(id、create_user、create_time、update_user、update_time、is_delete)。

设计原则

  • 所有模型继承 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 字段类型说明
varcharCharField短文本,需指定 max_length
textTextField长文本
intIntegerField整数
datetimeDateTimeField日期时间
dateDateField日期
floatFloatField浮点数
decimalDecimalField精确小数
booleanBooleanField布尔值

字段属性

属性说明示例
null数据库是否允许 NULLnull=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-禁用'
)

选项定义约定

  • 选项定义为类属性,命名为 {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 配置。

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