声明式映射样式


正如 Declarative Mapping 中介绍的那样,Declarative Mapping 是在现代 SQLAlchemy 中构造 Map 的典型方式。本节将概述可用于 Declarative mapper 配置的表单。


使用声明式基类


最常见的方法是通过子类化 DeclarativeBase 超类来生成“Declarative Base”类:

from sqlalchemy.orm import DeclarativeBase


# declarative base class
class Base(DeclarativeBase):
    pass


还可以在给定现有 Registry 中将其分配为名为 注册表

from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import registry

reg = registry()


# declarative base class
class Base(DeclarativeBase):
    registry = reg


在 2.0 版更改: DeclarativeBase 超类取代了 declarative_base() 函数和 registry.generate_base() 方法;超类方法与 PEP 484 工具集成,无需使用插件。有关迁移说明,请参阅 ORM Declarative Models


使用声明式基类,新的 Map 类被声明为 base 的子类:

from datetime import datetime
from typing import List
from typing import Optional

from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    name: Mapped[str]
    fullname: Mapped[Optional[str]]
    nickname: Mapped[Optional[str]] = mapped_column(String(64))
    create_date: Mapped[datetime] = mapped_column(insert_default=func.now())

    addresses: Mapped[List["Address"]] = relationship(back_populates="user")


class Address(Base):
    __tablename__ = "address"

    id = mapped_column(Integer, primary_key=True)
    user_id = mapped_column(ForeignKey("user.id"))
    email_address: Mapped[str]

    user: Mapped["User"] = relationship(back_populates="addresses")


在上面,Base 类用作要映射的新类的基础,如上所示,新映射的类 UserAddress 就是构造的。


对于构造的每个子类,类的主体遵循声明式映射方法,该方法在幕后定义 TableMapper 对象,这些对象构成了一个完整的映射。


另请参阅


使用声明式的表配置 - 描述如何指定要生成的映射的组件,包括有关使用 mapped_column() 的注释和选项 构造以及它如何与 Mapped 注解类型交互


具有声明式的映射器配置 - 描述所有其他 Declarative 中 ORM 映射器配置的各个方面,包括 relationship() 配置、SQL 表达式和 Mapper 参数


使用 Decorator 的声明式映射 (无声明式基)


作为使用“声明性基”类的替代方法是使用类似于“经典”映射的命令式技术显式地将声明性映射应用于类,或者更简洁地使用装饰器。registry.mapped() 函数是一个类装饰器,可以应用于任何没有层次结构的 Python 类。否则,Python 类通常以声明式样式配置。


下面的示例使用 registry.mapped() 设置与上一节中所示相同的映射 decorator 而不是使用 DeclarativeBase 超类:

from datetime import datetime
from typing import List
from typing import Optional

from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import registry
from sqlalchemy.orm import relationship

mapper_registry = registry()


@mapper_registry.mapped
class User:
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    name: Mapped[str]
    fullname: Mapped[Optional[str]]
    nickname: Mapped[Optional[str]] = mapped_column(String(64))
    create_date: Mapped[datetime] = mapped_column(insert_default=func.now())

    addresses: Mapped[List["Address"]] = relationship(back_populates="user")


@mapper_registry.mapped
class Address:
    __tablename__ = "address"

    id = mapped_column(Integer, primary_key=True)
    user_id = mapped_column(ForeignKey("user.id"))
    email_address: Mapped[str]

    user: Mapped["User"] = relationship(back_populates="addresses")


当使用上述样式时,特定类的映射将仅 如果 Decorator 直接应用于该类,则 continue 。对于继承 mappings(在 Mapping Class Inheritance Hierarchies中有详细描述),装饰器应该应用于要映射的每个子类:

from sqlalchemy.orm import registry

mapper_registry = registry()


@mapper_registry.mapped
class Person:
    __tablename__ = "person"

    person_id = mapped_column(Integer, primary_key=True)
    type = mapped_column(String, nullable=False)

    __mapper_args__ = {
        "polymorphic_on": type,
        "polymorphic_identity": "person",
    }


@mapper_registry.mapped
class Employee(Person):
    __tablename__ = "employee"

    person_id = mapped_column(ForeignKey("person.person_id"), primary_key=True)

    __mapper_args__ = {
        "polymorphic_identity": "employee",
    }


声明式表命令式表 table 配置样式可以与 Declarative Base 一起使用 或 Declarative mapping 的装饰器样式。


当将 SQLAlchemy 声明式映射与其他类插桩系统(如 dataclassesattrs)结合使用时,映射的装饰器形式非常有用,但请注意,SQLAlchemy 2.0 现在还具有与 Declarative Base 类的数据类集成功能。