Skip to content

BaseModel 设计

概述

所有业务模型都继承 BaseModel,提供统一的主键生成、软删除、审计字段。

源码

python
from nanoid import generate
from sqlalchemy import Column, String, DateTime, Boolean, Integer
from sqlalchemy.sql import func

class BaseModel(Base):
    """公共基础模型"""
    __abstract__ = True

    id = Column(String(21), primary_key=True, default=generate_nanoid)
    sort = Column(Integer, default=0, comment="排序")
    is_deleted = Column(Boolean, default=False, index=True, comment="是否删除")
    sys_create_datetime = Column(DateTime, server_default=func.now())
    sys_update_datetime = Column(DateTime, server_default=func.now(), onupdate=func.now())
    sys_creator_id = Column(String(21), nullable=True, comment="创建人ID")
    sys_modifier_id = Column(String(21), nullable=True, comment="修改人ID")
    sys_dept_id = Column(String(21), nullable=True, comment="部门ID")

字段说明

字段类型说明
idString(21)NanoID 主键,21 位随机字符串
sortInteger排序字段,默认 0,降序排列
is_deletedBoolean软删除标记,有索引
sys_create_datetimeDateTime创建时间,数据库层自动填充
sys_update_datetimeDateTime更新时间,数据库层自动更新
sys_creator_idString(21)创建人 ID(逻辑外键 → core_user)
sys_modifier_idString(21)修改人 ID(逻辑外键 → core_user)
sys_dept_idString(21)所属部门 ID(逻辑外键 → core_dept)

设计要点

NanoID 主键

使用 NanoID 替代自增 ID 或标准 UUID:

  • 长度:21 位,比 UUID 短(36 位)
  • 安全性:不暴露数据量和顺序
  • 分布式友好:无需中心化 ID 生成器
  • URL 安全:仅使用 A-Za-z0-9_- 字符
python
from nanoid import generate

def generate_nanoid() -> str:
    return generate(size=21)

软删除

通过 is_deleted 字段实现逻辑删除:

  • is_deleted=False:正常数据
  • is_deleted=True:已删除数据

BaseService 的所有查询方法默认过滤已删除数据。如需物理删除,设置 hard=True

审计字段自动填充

BaseService 在创建和更新时自动填充审计字段:

  • 创建时:自动设置 sys_creator_idsys_dept_id(从请求上下文获取)
  • 更新时:自动设置 sys_modifier_id(从请求上下文获取)
  • 时间字段由数据库层自动管理

逻辑外键

sys_creator_idsys_modifier_idsys_dept_id 都使用逻辑外键,不创建数据库外键约束。

使用示例

python
from sqlalchemy import Column, String, Text, Boolean, Integer
from app.base_model import BaseModel

class Customer(BaseModel):
    """客户模型"""
    __tablename__ = "biz_customer"

    name = Column(String(100), nullable=False, comment="客户名称")
    phone = Column(String(20), nullable=True, comment="电话")
    email = Column(String(100), nullable=True, comment="邮箱")
    address = Column(Text, nullable=True, comment="地址")
    level = Column(Integer, default=0, comment="客户等级")
    is_active = Column(Boolean, default=True, comment="是否启用")

命名规范

  • 表名:小写 + 下划线,模块前缀(如 core_userbiz_customer
  • 字段:小写 + 下划线
  • 字段注释:所有字段必须添加 comment
  • 字符串字段:指定长度(如 String(100)

Released under the MIT License.