base_model.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. # -*- coding: utf-8 -*-
  2. from typing import Optional
  3. from datetime import datetime
  4. from sqlalchemy import DateTime, String, Integer, Text, ForeignKey
  5. from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, declared_attr, relationship
  6. from sqlalchemy.ext.asyncio import AsyncAttrs
  7. from typing import TYPE_CHECKING
  8. if TYPE_CHECKING:
  9. from app.api.v1.module_system.user.model import UserModel
  10. from app.utils.common_util import uuid4_str
  11. class MappedBase(AsyncAttrs, DeclarativeBase):
  12. """
  13. 声明式基类
  14. `AsyncAttrs <https://docs.sqlalchemy.org/en/20/orm/extensions/asyncio.html#sqlalchemy.ext.asyncio.AsyncAttrs>`__
  15. `DeclarativeBase <https://docs.sqlalchemy.org/en/20/orm/declarative_config.html>`__
  16. `mapped_column() <https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.mapped_column>`__
  17. 兼容 SQLite、MySQL 和 PostgreSQL
  18. """
  19. __abstract__: bool = True
  20. class ModelMixin(MappedBase):
  21. """
  22. 模型混入类 - 提供通用字段和功能
  23. 基础模型混合类 Mixin: 一种面向对象编程概念, 使结构变得更加清晰
  24. 数据隔离设计原则:
  25. ==================
  26. 数据权限 (created_id/updated_id):
  27. - 配合角色的data_scope字段实现精细化权限控制
  28. - 1:仅本人
  29. - 2:本部门
  30. - 3:本部门及以下
  31. - 4:全部数据
  32. - 5:自定义
  33. SQLAlchemy加载策略说明:
  34. - select(默认): 延迟加载,访问时单独查询
  35. - joined: 使用LEFT JOIN预加载
  36. - selectin: 使用IN查询批量预加载(推荐用于一对多)
  37. - subquery: 使用子查询预加载
  38. - raise/raise_on_sql: 禁止加载
  39. - noload: 不加载,返回None
  40. - immediate: 立即加载
  41. - write_only: 只写不读
  42. - dynamic: 返回查询对象,支持进一步过滤
  43. """
  44. __abstract__: bool = True
  45. # 基础字段
  46. id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment='主键ID')
  47. uuid: Mapped[str] = mapped_column(String(64), default=uuid4_str, nullable=False, unique=True, comment='UUID全局唯一标识')
  48. status: Mapped[str] = mapped_column(String(10), default='0', nullable=False, comment="是否启用(0:启用 1:禁用)")
  49. description: Mapped[str | None] = mapped_column(Text, default=None, nullable=True, comment="备注/描述")
  50. created_time: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, nullable=False, comment='创建时间')
  51. updated_time: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, onupdate=datetime.now, nullable=False, comment='更新时间')
  52. class UserMixin(MappedBase):
  53. """
  54. 用户审计字段 Mixin
  55. 用于记录数据的创建者和更新者
  56. 用于实现数据权限中的"仅本人数据权限"
  57. """
  58. __abstract__: bool = True
  59. created_id: Mapped[int | None] = mapped_column(
  60. Integer,
  61. ForeignKey('sys_user.id', ondelete="SET NULL", onupdate="CASCADE"),
  62. default=None,
  63. nullable=True,
  64. index=True,
  65. comment="创建人ID"
  66. )
  67. updated_id: Mapped[int | None] = mapped_column(
  68. Integer,
  69. ForeignKey('sys_user.id', ondelete="SET NULL", onupdate="CASCADE"),
  70. default=None,
  71. nullable=True,
  72. index=True,
  73. comment="更新人ID"
  74. )
  75. @declared_attr
  76. def created_by(cls) -> Mapped[Optional["UserModel"]]:
  77. """
  78. 创建人关联关系(延迟加载,避免循环依赖)
  79. """
  80. return relationship(
  81. "UserModel",
  82. lazy="selectin",
  83. foreign_keys=lambda: cls.created_id,
  84. uselist=False
  85. )
  86. @declared_attr
  87. def updated_by(cls) -> Mapped[Optional["UserModel"]]:
  88. """
  89. 更新人关联关系(延迟加载,避免循环依赖)
  90. """
  91. return relationship(
  92. "UserModel",
  93. lazy="selectin",
  94. foreign_keys=lambda: cls.updated_id,
  95. uselist=False
  96. )