Skip to content

Latest commit

 

History

History
215 lines (185 loc) · 8.73 KB

2.模型定义规范.md

File metadata and controls

215 lines (185 loc) · 8.73 KB

模型定义规范

1.常用的字段类型

  • db.INTEGER
    • 对应mysql int 类型
  • db.BIGINT
    • 对应mysql bigint 类型
    • 推荐作为主键,自增
  • sqlalchemy.dialects.mysql.types.TINYINT
    • 对应mysql tinyint 类型
    • 表示类型字段推荐使用
    • 仅存储0,1时推荐使用
  • db.CHAR(length: int)
    • 对应mysql char(n) 类型
    • 建议设置 nullable=False, default=''
  • db.VARCHAR(length: int)
    • 对应mysql varchar(n) 类型
    • 建议设置 nullable=False, default=''
  • db.VARCHAR(length: int, collation: str = 'xxx_bin')
    • 推荐设置 db.VARCHAR(length=50, collation='utf8mb4_bin')
      • 对应mysql varchar(n) binary 类型
      • 实际会转化为 varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
  • db.DATE
    • 对应mysql date 类型
  • db.DATETIME
    • 禁止使用,不支持 mysql datetime(6)
  • sqlalchemy.dialects.mysql.types.DATETIME(fsp: int)
    • 推荐定义 DATETIME(fsp=6)
    • 对应mysql datetime(6)
  • db.DECIMAL(precision: int, scale: int)
    • 绝对精度类型,对应mysql decimal(M, D) 类型
    • precision <==> M,表示数字总个数
    • scale <==> D,表示小数位的个数
    • 建议金钱相关字段使用
  • db.FLOAT
    • 低精度,禁止使用
  • sqlalchemy.dialects.mysql.types.TEXT
    • 对应mysql text 类型
  • sqlalchemy.dialects.mysql.types.LONGTEXT
    • 对应mysql longtext 类型
  • db.JSON
    • 对应mysql json 类型
    • mysql 5.7 开始支持
  • 外键相关
    • 不推荐使用,建议手工指定
    • db.relationship(argument: str, *, backref: str)
      • argument: 模型类名
      • backref: 反向关联的属性名
      • 注意:
        • 正向关联,返回 Model
        • 反向关联,返回 List[Model]
      • 不推荐,使用时为全字段查询
    • db.ForeignKey(column: str)
      • column: 表名.字段名,如 db.ForeignKey('t_xxx.xxx_id')
      • 可用可不用,不做强制要求
        • 使用:关联查询可省略连接条件;关联关系不清晰
        • 不使用:关联查询需要手动指定连接条件;关联关系清晰
      • 使用后禁止使用flask命令生成表结构,存在外键,降低并发

2.常用字段属性

  • primary_key: bool
    • 主键
  • autoincrement: bool
    • 自增
  • comment: str
    • 注释
  • nullable: bool
    • 是否为空
  • default: Any
    • 默认值,支持函数
    • 不会映射到mysql
  • onupdate: Any
    • 更新时触发,支持函数
    • 不会映射到mysql
  • index: bool
    • 是否添加二级索引
  • unique: bool
    • 是否添加唯一索引

3.xxx

  • tablename: str
    • 表名,会映射到mysql上
  • table_args: dict
    • comment: str
      • 表注释,会映射到mysql上

4.模型定义示例

# coding: utf-8

import datetime
from enum import IntEnum, unique
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.mysql.types import TINYINT, TEXT, LONGTEXT, DATETIME

from libs.uuid import make_uuid

db = SQLAlchemy()


class Xxx(db.Model):

    __tablename__ = 't_xxx'
    __table_args__ = {'comment': 'xxx表'}

    @unique
    class XxxTypeEnum(IntEnum):
        """xxx类型枚举类"""

        TYPE_ONE = 1    # 类型1
        TYPE_TWO = 2    # 类型2
        TYPE_THREE = 3  # 类型3

    # 主键自增id,要求使用bigint且业务无关
    id = db.Column(db.BIGINT, primary_key=True, autoincrement=True, comment='表id')
    # xxx_id使用uuid,固定32位长度,唯一键
    xxx_id = db.Column(db.CHAR(length=32), nullable=False, default=make_uuid, unique=True, comment='xxxid')
    # 类型字段建议使用tinyint,针对choices扩展出枚举类,方便管理
    xxx_type = db.Column(TINYINT, nullable=False, default=XxxTypeEnum.TYPE_ONE.value, comment='xxx类型: 1类型1, 2类型2 3类型3')
    # varchar类型统一定义成 not null default ''
    xxx_name = db.Column(db.VARCHAR(length=50), nullable=False, default='', comment='xxx名称')
    # varchar 区分大小写,指定collation,不要使用VARBINARY
    xxx_name_bin = db.Column(db.VARCHAR(length=50, collation='utf8mb4_bin'), nullable=False, default='', comment='xxx名称(区分大小写)')
    # 价格使用
    xxx_price = db.Column(db.DECIMAL(precision=10, scale=2), nullable=False, default=0, comment='xxx价格')
    # 每个表必加的三个字段
    # 是否已删除,使用ORM布尔类型,对应mysql的tinyint
    is_deleted = db.Column(TINYINT, nullable=False, default=0, comment='是否已删除:0未删除 1已删除')
    # 模型创建时自动更新
    create_time = db.Column(DATETIME(fsp=6), nullable=False, default=datetime.datetime.now, comment='创建时间')
    # 模型修改时自动更新
    update_time = db.Column(DATETIME(fsp=6), nullable=False, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')

    xxx_detail = db.relationship('XxxDetail')
    yyy = db.relationship('Yyy')

    """生成的表结构
    CREATE TABLE `t_xxx` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '表id',
      `xxx_id` char(32) NOT NULL COMMENT 'xxxid',
      `xxx_type` tinyint(4) NOT NULL COMMENT 'xxx类型: 1类型1, 2类型2 3类型3',
      `xxx_name` varchar(50) NOT NULL COMMENT 'xxx名称',
      `xxx_name_bin` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'xxx名称(区分大小写)',
      `xxx_price` decimal(10,2) NOT NULL COMMENT 'xxx价格',
      `is_deleted` tinyint(4) NOT NULL COMMENT '是否已删除:0未删除 1已删除',
      `create_time` datetime(6) NOT NULL COMMENT '创建时间',
      `update_time` datetime(6) NOT NULL COMMENT '更新时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `xxx_id` (`xxx_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='xxx表'
    """


class XxxDetail(db.Model):
    """xxx子表(详情表)

    有些情况,需要将大字段从源表中垂直拆分出来,形成一个子表,以减少查询I/O
    """

    __tablename__ = 't_xxx_detail'
    __table_args__ = {'comment': 'xxx详情表'}

    id = db.Column(db.BIGINT, primary_key=True, autoincrement=True, comment='表id')
    # 一对一外键
    xxx_id = db.Column(db.CHAR(length=32), db.ForeignKey('t_xxx.xxx_id'), unique=True, comment='xxxid')
    # 大字段类型,统一设置nullable=True
    content = db.Column(TEXT, nullable=True, comment='内容')
    long_content = db.Column(LONGTEXT, nullable=True, comment='长内容')
    name_list = db.Column(db.JSON, nullable=True, comment='名称列表')

    """生成的表结构
    CREATE TABLE `t_xxx_detail` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '表id',
      `xxx_id` char(32) DEFAULT NULL COMMENT 'xxxid',
      `content` text COMMENT '内容',
      `long_content` longtext COMMENT '长内容',
      `name_list` json DEFAULT NULL COMMENT '名称列表',
      PRIMARY KEY (`id`),
      UNIQUE KEY `xxx_id` (`xxx_id`),
      CONSTRAINT `t_xxx_detail_ibfk_1` FOREIGN KEY (`xxx_id`) REFERENCES `t_xxx` (`xxx_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='xxx详情表'
    """


class Yyy(db.Model):

    __tablename__ = 't_yyy'
    __table_args__ = {'comment': 'yyy表'}

    id = db.Column(db.BIGINT, primary_key=True, autoincrement=True, comment='表id')
    yyy_id = db.Column(db.CHAR(length=32), nullable=False, default=make_uuid, unique=True, comment='yyyid')
    xxx_id = db.Column(db.CHAR(length=32), db.ForeignKey('t_xxx.xxx_id'), comment='xxxid')
    is_deleted = db.Column(TINYINT, nullable=False, default=0, comment='是否已删除:0未删除 1已删除')
    create_time = db.Column(DATETIME(fsp=6), nullable=False, default=datetime.datetime.now, comment='创建时间')
    update_time = db.Column(DATETIME(fsp=6), nullable=False, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')

    """生成的表结构
    CREATE TABLE `t_yyy` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '表id',
      `yyy_id` char(32) NOT NULL COMMENT 'yyyid',
      `xxx_id` char(32) DEFAULT NULL COMMENT 'xxxid',
      `is_deleted` tinyint(4) NOT NULL COMMENT '是否已删除:0未删除 1已删除',
      `create_time` datetime(6) NOT NULL COMMENT '创建时间',
      `update_time` datetime(6) NOT NULL COMMENT '更新时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `yyy_id` (`yyy_id`),
      KEY `xxx_id` (`xxx_id`),
      CONSTRAINT `t_yyy_ibfk_1` FOREIGN KEY (`xxx_id`) REFERENCES `t_xxx` (`xxx_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='yyy表
    """