SQLAlchemy中的mapped_column和Column有什么区别?

use*_*284 17 python sqlalchemy

我是 SQLAlchemy 的新手,我在文档中看到旧版本(列)可以直接与较新的“mapped_column”交换。

使用mapped_column 比Column 有什么优势吗?你能坚持旧的“专栏”吗?

Ian*_*son 16

我认为最初Column是在较低的“核心”/sqlalchemy.sql较高的 ORM 层中使用的。这造成了目的冲突。因此mapped_column,现在取代Column使用 ORM 层添加更多核心层无法使用的功能。核心层将继续使用Column。所以我认为它只是为了帮助您使用 ORM 更快或更简洁地完成更多工作。

在 declarative-table-with-mapped-column下面有一个关于它们的简介,标题为“mapped_column() 取代了 Column() 的使用” 。

以下是一些使用 postgresql 的基本示例。

请参阅SQL最后的输出。

class Base(DeclarativeBase):
    pass

class Controller(Base):
    __tablename__ = "controllers"

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column() # Example 1
    index: Mapped[int] # Example 2
    configured: Mapped[Optional[bool]] # Example 3
    setup_mode: Mapped[bool] # Example 4
    created_at = Column(DateTime(timezone=True)) # Example 5
Run Code Online (Sandbox Code Playgroud)

实施例1

列类型派生自类型提示,在本例中VARCHAR是派生自。str

name: Mapped[str] = mapped_column()
Run Code Online (Sandbox Code Playgroud)

实施例2

mapped_column为空时,可以完全忽略它,这仍然有效,即。INTEGER源自int.

index: Mapped[int]
Run Code Online (Sandbox Code Playgroud)

实施例3

当使用Optionalfromtyping时,列将允许NULL,即。nullable=True

configured: Mapped[Optional[bool]]
Run Code Online (Sandbox Code Playgroud)

实施例4

Optional使用时,列将不允许NULL,即。nullable=False

setup_mode: Mapped[bool]
Run Code Online (Sandbox Code Playgroud)

实施例5

Column仍然可以mapped_column在不使用类型提示的情况下一起使用。

created_at = Column(DateTime(timezone=True))
Run Code Online (Sandbox Code Playgroud)

类型检查示例

运行此代码mypy将产生类似于以下内容的错误error: "Controller" has no attribute "unknown_attribute" [attr-defined]


with Session(engine) as session:
    controller = session.scalars(select(Controller).limit(1)).first()
    if controller is not None:
        assert controller.created_at
        assert controller.unknown_attribute
Run Code Online (Sandbox Code Playgroud)

最终CREATE TABLE输出

CREATE TABLE controllers (
    id SERIAL NOT NULL, 
    name VARCHAR NOT NULL, 
    index INTEGER NOT NULL, 
    configured BOOLEAN, 
    setup_mode BOOLEAN NOT NULL, 
    created_at TIMESTAMP WITH TIME ZONE, 
    PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)

一些“为什么”

  • 允许更多没有意义的特定于 Orm 的功能Column()
  • 减少样板代码
    • intstrdatetimeOptional等可从 python 获得,无需sqlalchemy导入
    • 如果类型可以从 typehint 派生并且不需要特殊配置,则可以省略整个列/mapped_column 定义,即。index: Mapped[int]
  • 允许类型检查器更好地检查类型
    • 可以通过使用数据类集成之类的东西来扩展检查,但这超出了这个问题