SqlAlchemy 2.0 中文文档(十)

2024-06-26 14:33:47 浏览数 (2)

原文:docs.sqlalchemy.org/en/20/contents.html

非传统映射

原文:docs.sqlalchemy.org/en/20/orm/nonstandard_mappings.html

将类映射到多个表

映射器可以构造与任意关系单元(称为 selectables)相对应的类,除了普通表之外。例如,join() 函数创建了一个包含多个表的可选择单元,具有自己的复合主键,可以与 Table 相同的方式映射:

代码语言:javascript复制
from sqlalchemy import Table, Column, Integer, String, MetaData, join, ForeignKey
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import column_property

metadata_obj = MetaData()

# define two Table objects
user_table = Table(
    "user",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("name", String),
)

address_table = Table(
    "address",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("user_id", Integer, ForeignKey("user.id")),
    Column("email_address", String),
)

# define a join between them.  This
# takes place across the user.id and address.user_id
# columns.
user_address_join = join(user_table, address_table)

class Base(DeclarativeBase):
    metadata = metadata_obj

# map to it
class AddressUser(Base):
    __table__ = user_address_join

    id = column_property(user_table.c.id, address_table.c.user_id)
    address_id = address_table.c.id

在上面的示例中,连接表示了 user 表和 address 表的列。user.idaddress.user_id 列通过外键相等,因此在映射中它们被定义为一个属性,即 AddressUser.id,使用 column_property() 来指示一个特殊的列映射。基于这部分配置,当发生 flush 时,映射将把新的主键值从 user.id 复制到 address.user_id 列。

另外,address.id 列被显式映射到一个名为 address_id 的属性。这是为了消除歧义,将 address.id 列的映射与同名的 AddressUser.id 属性区分开来,这里已经被分配为引用 user 表与 address.user_id 外键结合的表。

上面映射的自然主键是 (user.id, address.id) 的组合,因为这些是 useraddress 表的联合主键列。AddressUser 对象的标识将根据这两个值,并且从 AddressUser 对象表示为 (AddressUser.id, AddressUser.address_id)

当涉及到 AddressUser.id 列时,大多数 SQL 表达式将仅使用映射列列表中的第一列,因为这两列是同义的。然而,对于特殊用例,比如 GROUP BY 表达式,在这种情况下需要同时引用两列,并且在使用正确的上下文时,即考虑到别名和类似情况时,可以使用访问器 Comparator.expressions

代码语言:javascript复制
stmt = select(AddressUser).group_by(*AddressUser.id.expressions)

新功能在版本 1.3.17 中添加:增加了 Comparator.expressions 访问器。

注意

如上所示的针对多个表的映射支持持久化,即对目标表中的行进行 INSERT、UPDATE 和 DELETE。然而,它不支持一次为一个记录在一个表上执行 UPDATE 并在其他表上同时执行 INSERT 或 DELETE 的操作。也就是说,如果一个记录 PtoQ 被映射到“p”和“q”表,其中它基于“p”和“q”的 LEFT OUTER JOIN 有一行,如果进行一个 UPDATE 来修改现有记录中“q”表中的数据,那么“q”中的行必须存在;如果主键标识已经存在,它不会发出 INSERT。如果行不存在,对于大多数支持报告 UPDATE 受影响行数的 DBAPI 驱动程序,ORM 将无法检测到更新的行并引发错误;否则,数据将被静默忽略。

一个允许在相关行上“即时”插入的方法可能会使用.MapperEvents.before_update 事件,并且看起来像:

代码语言:javascript复制
from sqlalchemy import event

@event.listens_for(PtoQ, "before_update")
def receive_before_update(mapper, connection, target):
    if target.some_required_attr_on_q is None:
        connection.execute(q_table.insert(), {"id": target.id})

在上面的例子中,通过使用Table.insert()创建一个 INSERT 构造,然后使用给定的Connection执行它,将一行 INSERT 到q_table表中,这个 Connection 与用于发出 flush 过程中的其他 SQL 的 Connection 相同。用户提供的逻辑必须检测到从“p”到“q”的 LEFT OUTER JOIN 没有“q”侧的条目。## 对任意子查询映射类

类似于针对连接的映射,也可以将一个普通的select()对象与映射器一起使用。下面的示例片段说明了将一个名为Customer的类映射到一个包含与子查询连接的select()中:

代码语言:javascript复制
from sqlalchemy import select, func

subq = (
    select(
        func.count(orders.c.id).label("order_count"),
        func.max(orders.c.price).label("highest_order"),
        orders.c.customer_id,
    )
    .group_by(orders.c.customer_id)
    .subquery()
)

customer_select = (
    select(customers, subq)
    .join_from(customers, subq, customers.c.id == subq.c.customer_id)
    .subquery()
)

class Customer(Base):
    __table__ = customer_select

在上面,由customer_select表示的完整行将是customers表的所有列,以及subq子查询暴露的那些列,即order_counthighest_ordercustomer_id。将Customer类映射到这个可选择的内容,然后创建一个包含这些属性的类。

当 ORM 持久化Customer的新实例时,实际上只有customers表会收到 INSERT。这是因为orders表的主键没有在映射中表示;ORM 只会对已经映射了主键的表发出 INSERT。

注意

映射到任意 SELECT 语句的做法,特别是像上面这样复杂的语句,几乎从不需要;它必然倾向于生成复杂的查询,这些查询通常比直接构造查询要低效。这种做法在某种程度上基于 SQLAlchemy 的非常早期历史,其中Mapper构造被认为是主要的查询接口;在现代用法中,Query对象可以用于构造几乎任何 SELECT 语句,包括复杂的复合语句,并且应优先于“映射到可选”的方法。

为一个类映射多个映射器

在现代的 SQLAlchemy 中,一个特定的类一次只能由一个所谓的主要映射器(mapper)映射。这个映射器涉及三个主要功能领域:查询、持久性和对映射类的仪器化。主要映射器的理论基础与以下事实相关:Mapper修改了类本身,不仅将其持久化到特定的Table中,还对类上的属性进行了仪器化,这些属性根据表元数据特别结构化。不能有多个映射器与一个类同等相关,因为只有一个映射器可以实际仪器化该类。

“非主要”映射器的概念已经存在多个 SQLAlchemy 版本,但从 1.3 版本开始,此功能已被弃用。其中一个非主要映射器有用的情况是构建与备用可选择类之间的关系时。现在可以使用aliased构造来满足此用例,并在 Relationship to Aliased Class 中进行了描述。

就一个类可以在不同情境下被完全持久化到不同表中的用例而言,早期版本的 SQLAlchemy 提供了一个来自 Hibernate 的功能,称为“实体名称”功能。然而,在 SQLAlchemy 中,一旦映射类本身成为 SQL 表达式构造的来源,即类的属性直接链接到映射表列,这个用例就变得不可行了。该功能被移除,并被一个简单的面向配方的方法取代,以完成此任务而不产生任何仪器化的歧义——创建新的子类,每个类都被单独映射。该模式现在作为一种配方在Entity Name中提供。

将一个类映射到多个表

Mappers 可以针对任意关系单元(称为selectables)进行构建,而不仅仅是普通的表。例如,join() 函数创建了一个包含多个表的可选单元,其中包括其自己的复合主键,可以与Table 以相同的方式映射:

代码语言:javascript复制
from sqlalchemy import Table, Column, Integer, String, MetaData, join, ForeignKey
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import column_property

metadata_obj = MetaData()

# define two Table objects
user_table = Table(
    "user",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("name", String),
)

address_table = Table(
    "address",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("user_id", Integer, ForeignKey("user.id")),
    Column("email_address", String),
)

# define a join between them.  This
# takes place across the user.id and address.user_id
# columns.
user_address_join = join(user_table, address_table)

class Base(DeclarativeBase):
    metadata = metadata_obj

# map to it
class AddressUser(Base):
    __table__ = user_address_join

    id = column_property(user_table.c.id, address_table.c.user_id)
    address_id = address_table.c.id

在上面的示例中,连接表示了useraddress表的列。 user.idaddress.user_id列由外键等于,因此在映射中它们被定义为一个属性AddressUser.id,使用column_property()指示专门的列映射。根据配置的这一部分,当发生刷新时,映射将新的主键值从user.id复制到address.user_id列。

另外,address.id列显式映射到名为address_id的属性。这是为了消除歧义,将address.id列的映射与同名的AddressUser.id属性分开,这里已经被分配为引用user表与address.user_id外键的属性。

上述映射的自然主键是(user.id, address.id)的组合,因为这些是useraddress表的主键列合并在一起。 AddressUser对象的标识将根据这两个值,并且从AddressUser对象表示为(AddressUser.id, AddressUser.address_id)

在引用AddressUser.id列时,大多数 SQL 表达式将仅使用映射列列表中的第一列,因为这两列是同义的。但是,对于特殊用例,例如必须同时引用两列的 GROUP BY 表达式,同时考虑到适当的上下文,即适应别名等,可以使用访问器Comparator.expressions

代码语言:javascript复制
stmt = select(AddressUser).group_by(*AddressUser.id.expressions)

1.3.17 版本中的新内容:添加了Comparator.expressions 访问器。

注意

如上所示的对多个表的映射支持持久性,即对目标表中的行进行 INSERT、UPDATE 和 DELETE 操作。然而,它不支持在一条记录中同时对一个表进行 UPDATE 并在其他表上执行 INSERT 或 DELETE 的操作。也就是说,如果将记录 PtoQ 映射到“p”和“q”表,其中它基于“p”和“q”的 LEFT OUTER JOIN 的行,如果进行更新以更改现有记录中“q”表中的数据,则“q”中的行必须存在;如果主键标识已经存在,它不会发出 INSERT。如果行不存在,对于大多数支持报告 UPDATE 受影响行数的 DBAPI 驱动程序,ORM 将无法检测到更新的行并引发错误;否则,数据将被静默忽略。

允许在“插入”相关行时使用的配方可能利用.MapperEvents.before_update事件,并且看起来像:

代码语言:javascript复制
from sqlalchemy import event

@event.listens_for(PtoQ, "before_update")
def receive_before_update(mapper, connection, target):
    if target.some_required_attr_on_q is None:
        connection.execute(q_table.insert(), {"id": target.id})

在上述情况下,通过使用Table.insert()创建一个 INSERT 构造将一行插入q_table表,然后使用给定的Connection执行它,这与用于发出刷新过程中的其他 SQL 的相同连接。用户提供的逻辑必须检测从“p”到“q”的 LEFT OUTER JOIN 是否没有“q”方面的条目。

将类映射到任意子查询

类似于对连接进行映射,也可以将一个普通的select()对象与映射器一起使用。下面的示例片段说明了将名为Customer的类映射到包含与子查询连接的select()的过程:

代码语言:javascript复制
from sqlalchemy import select, func

subq = (
    select(
        func.count(orders.c.id).label("order_count"),
        func.max(orders.c.price).label("highest_order"),
        orders.c.customer_id,
    )
    .group_by(orders.c.customer_id)
    .subquery()
)

customer_select = (
    select(customers, subq)
    .join_from(customers, subq, customers.c.id == subq.c.customer_id)
    .subquery()
)

class Customer(Base):
    __table__ = customer_select

在上面,由customer_select表示的完整行将是customers表的所有列,以及subq子查询暴露的那些列,即order_counthighest_ordercustomer_id。将Customer类映射到这个可选择的类,然后创建一个包含这些属性的类。

当 ORM 持久化Customer的新实例时,实际上只有customers表会收到 INSERT。这是因为orders表的主键没有在映射中表示;ORM 只会对已映射主键的表发出 INSERT。

注意

对任意 SELECT 语句进行映射的实践,特别是上面那种复杂的情况,几乎从不需要;这必然会产生复杂的查询,通常比直接构造的查询效率低。这种做法在某种程度上基于 SQLAlchemy 的早期历史,其中Mapper构造旨在代表主要的查询接口;在现代用法中,Query对象可用于构造几乎任何 SELECT 语句,包括复杂的复合语句,并且应优先使用“映射到可选择”方法。

一个类对应多个映射器

在现代的 SQLAlchemy 中,一个特定的类在任何时候只被一个所谓的主要映射器所映射。这个映射器涉及三个主要功能领域:查询、持久化和对映射类的仪器化。主要映射器的理念与以下事实相关:Mapper不仅修改类本身,而且将其持久化到特定的Table,还会根据表元数据结构化地仪器化类上的属性。不可能有多个映射器与一个类一样平等地关联,因为只有一个映射器实际上可以仪器化这个类。

“非主要”映射器的概念在许多版本的 SQLAlchemy 中一直存在,但自版本 1.3 起,此功能已不建议使用。唯一需要非主要映射器的情况是在构造与另一个可选择的类的关系时。现在,可以使用aliased构造来满足这个用例,并在关系到别名类中进行描述。

就一个类在不同情境下可以完全持久化到不同表的用例而言,SQLAlchemy 的早期版本提供了一个从 Hibernate 改编而来的功能,称为“实体名称”功能。然而,在 SQLAlchemy 中,一旦映射的类本身成为 SQL 表达式构造的源,即类的属性直接链接到映射表的列,这个用例就变得不可行了。该功能被移除,并用一个简单的基于配方的方法来完成这个任务,而不会有任何仪器化的歧义 - 即创建新的子类,每个类都单独映射。这种模式现在作为实体名称的配方可用。

配置版本计数器

原文:docs.sqlalchemy.org/en/20/orm/versioning.html

Mapper支持管理版本 ID 列,它是单个表列,每当对映射表进行UPDATE时,该列会递增或以其他方式更新其值。每次 ORM 发出UPDATEDELETE对行进行操作时,都会检查该值,以确保内存中持有的值与数据库值匹配。

警告

因为版本控制功能依赖于对象的内存记录的比较,所以该功能仅适用于Session.flush()过程,在此过程中 ORM 将单个内存中的行刷新到数据库。当执行多行 UPDATE 或 DELETE 时,该功能不会生效,使用Query.update()Query.delete()方法,因为这些方法仅发出 UPDATE 或 DELETE 语句,但否则无法直接访问受影响行的内容。

此功能的目的是检测两个并发事务在大致相同的时间修改同一行,或者在可能重用上一个事务的数据而不进行刷新的系统中提供对“过时”行的防护(例如,如果使用Sessionexpire_on_commit=False设置,可能会重用上一个事务的数据)。

简单版本计数

跟踪版本的最直接方法是向映射表添加一个整数列,然后在映射器选项中将其设为version_id_col

代码语言:javascript复制
class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    version_id = mapped_column(Integer, nullable=False)
    name = mapped_column(String(50), nullable=False)

    __mapper_args__ = {"version_id_col": version_id}

注意

强烈建议version_id列设为 NOT NULL。版本控制功能不支持版本列中的 NULL 值。

在上面的例子中,User映射使用version_id列跟踪整数版本。当首次刷新User类型的对象时,version_id列的值将为“1”。然后,稍后对表的 UPDATE 将始终以类似以下的方式发出:

代码语言:javascript复制
UPDATE  user  SET  version_id=:version_id,  name=:name
WHERE  user.id  =  :user_id  AND  user.version_id  =  :user_version_id
-- {"name": "new name", "version_id": 2, "user_id": 1, "user_version_id": 1}

上述 UPDATE 语句正在更新不仅与user.id = 1匹配的行,而且还要求user.version_id = 1,其中“1”是我们已知在此对象上使用的最后版本标识符。如果在其他地方的事务独立修改了该行,则此版本 id 将不再匹配,并且 UPDATE 语句将报告没有匹配的行;这是 SQLAlchemy 测试的条件,确保我们的 UPDATE(或 DELETE)语句匹配了恰好一行。如果没有匹配的行,这表明我们的数据版本已过时,并且会引发StaleDataError异常。

自定义版本计数器/类型

可以使用其他类型或计数器来进行版本控制。常见类型包括日期和 GUID。当使用备用类型或计数器方案时,SQLAlchemy 提供了使用version_id_generator参数的钩子,该参数接受一个版本生成可调用对象。此可调用对象会传递当前已知版本的值,并且预期返回后续版本。

例如,如果我们想使用随机生成的 GUID 跟踪User类的版本控制,我们可以这样做(请注意,某些后端支持原生 GUID 类型,但我们在这里使用简单的字符串进行说明):

代码语言:javascript复制
import uuid

class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    version_uuid = mapped_column(String(32), nullable=False)
    name = mapped_column(String(50), nullable=False)

    __mapper_args__ = {
        "version_id_col": version_uuid,
        "version_id_generator": lambda version: uuid.uuid4().hex,
    }

每次User对象需要进行 INSERT 或 UPDATE 操作时,持久化引擎将调用uuid.uuid4()。在这种情况下,我们的版本生成函数可以忽略version的传入值,因为uuid4()函数生成的标识符不需要任何先决条件值。如果我们使用的是顺序版本控制方案,例如数字或特殊字符系统,我们可以利用给定的version来帮助确定后续值。

另请参阅

跨后端通用 GUID 类型 ## 服务器端版本计数器

version_id_generator也可以配置为依赖于数据库生成的值。在这种情况下,数据库需要某种方式在行进行 INSERT 时生成新的标识符,以及在 UPDATE 时生成。对于 UPDATE 情况,通常需要一个更新触发器,除非所涉及的数据库支持其他一些本地版本标识符。特别是 PostgreSQL 数据库支持一个称为xmin的系统列,它提供了 UPDATE 版本控制。我们可以如下使用 PostgreSQL 的xmin列为我们的User类版本控制:

代码语言:javascript复制
from sqlalchemy import FetchedValue

class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    name = mapped_column(String(50), nullable=False)
    xmin = mapped_column("xmin", String, system=True, server_default=FetchedValue())

    __mapper_args__ = {"version_id_col": xmin, "version_id_generator": False}

使用上述映射,ORM 将依赖于xmin列自动提供版本 id 计数器的新值。

当 ORM 发出 INSERT 或 UPDATE 时,通常不会主动获取数据库生成的值,而是将这些列保留为“过期”,在下次访问它们时获取,除非设置了eager_defaults Mapper标志。但是,当使用服务器端版本列时,ORM 需要主动获取新生成的值。这样做是为了在任何并发事务可能再次更新之前设置版本计数器之前。最好同时在 INSERT 或 UPDATE 语句中使用 RETURNING 进行获取,否则,如果之后发出 SELECT 语句,则仍然存在潜在的竞争条件,版本计数器可能在获取之前更改。

当目标数据库支持 RETURNING 时,我们的User类的 INSERT 语句如下所示:

代码语言:javascript复制
INSERT  INTO  "user"  (name)  VALUES  (%(name)s)  RETURNING  "user".id,  "user".xmin
-- {'name': 'ed'}

在上述情况下,ORM 可以在一条语句中获取任何新生成的主键值以及服务器生成的版本标识符。当后端不支持 RETURNING 时,必须对每个INSERT 和 UPDATE 发出额外的 SELECT,这非常低效,还会引入可能丢失版本计数器的可能性:

代码语言:javascript复制
INSERT  INTO  "user"  (name)  VALUES  (%(name)s)
-- {'name': 'ed'}

SELECT  "user".version_id  AS  user_version_id  FROM  "user"  where
"user".id  =  :param_1
-- {"param_1": 1}

强烈建议仅在绝对必要时且仅在支持 RETURNING 的后端上使用服务器端版本计数器,目前支持的后端有 PostgreSQL、Oracle、MariaDB 10.5、SQLite 3.35 和 SQL Server。

编程或条件版本计数器

version_id_generator设置为 False 时,我们还可以以与分配任何其他映射属性相同的方式,在对象上编程(和有条件地)设置版本标识符。例如,如果我们使用了 UUID 示例,但将version_id_generator设置为False,我们可以随意设置版本标识符:

代码语言:javascript复制
import uuid

class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    version_uuid = mapped_column(String(32), nullable=False)
    name = mapped_column(String(50), nullable=False)

    __mapper_args__ = {"version_id_col": version_uuid, "version_id_generator": False}

u1 = User(name="u1", version_uuid=uuid.uuid4())

session.add(u1)

session.commit()

u1.name = "u2"
u1.version_uuid = uuid.uuid4()

session.commit()

我们也可以在不增加版本计数器的情况下更新我们的User对象;计数器的值将保持不变,并且 UPDATE 语句仍将针对先前的值进行检查。对于仅某些类别的 UPDATE 对并发问题敏感的方案,这可能很有用:

代码语言:javascript复制
# will leave version_uuid unchanged
u1.name = "u3"
session.commit()

简单版本计数

跟踪版本的最直接方法是向映射表添加一个整数列,然后将其设置为映射选项中的version_id_col

代码语言:javascript复制
class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    version_id = mapped_column(Integer, nullable=False)
    name = mapped_column(String(50), nullable=False)

    __mapper_args__ = {"version_id_col": version_id}

注意

强烈建议version_id列设置为 NOT NULL。版本控制功能不支持版本控制列中的 NULL 值。

上面,User映射使用列version_id跟踪整数版本。当首次刷新User类型的对象时,version_id列的值将为“1”。然后,稍后对表的 UPDATE 将始终以类似以下方式发出:

代码语言:javascript复制
UPDATE  user  SET  version_id=:version_id,  name=:name
WHERE  user.id  =  :user_id  AND  user.version_id  =  :user_version_id
-- {"name": "new name", "version_id": 2, "user_id": 1, "user_version_id": 1}

上述 UPDATE 语句正在更新不仅与 user.id = 1 匹配的行,而且还要求 user.version_id = 1,其中“1”是我们已知的此对象上一次使用的最后版本标识符。如果其他地方的事务独立修改了行,则此版本 ID 将不再匹配,UPDATE 语句将报告没有匹配的行;这是 SQLAlchemy 测试的条件,确保我们的 UPDATE(或 DELETE)语句仅匹配了一行。如果没有匹配的行,则表示我们的数据版本已过期,并且会引发 StaleDataError

自定义版本计数器 / 类型

其他类型的值或计数器可以用于版本控制。常见的类型包括日期和 GUID。当使用替代类型或计数器方案时,SQLAlchemy 提供了一个钩子来使用 version_id_generator 参数,该参数接受版本生成可调用对象。此可调用对象将传递当前已知版本的值,并且预计返回后续版本。

例如,如果我们想要使用随机生成的 GUID 跟踪我们的 User 类的版本控制,我们可以这样做(请注意,一些后端支持原生的 GUID 类型,但我们在这里使用简单的字符串进行演示):

代码语言:javascript复制
import uuid

class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    version_uuid = mapped_column(String(32), nullable=False)
    name = mapped_column(String(50), nullable=False)

    __mapper_args__ = {
        "version_id_col": version_uuid,
        "version_id_generator": lambda version: uuid.uuid4().hex,
    }

持久性引擎每次将 User 对象受到 INSERT 或 UPDATE 影响时都会调用 uuid.uuid4()。在这种情况下,我们的版本生成函数可以忽略 version 的传入值,因为 uuid4() 函数生成的标识符没有任何先决条件值。如果我们使用的是顺序版本控制方案,例如数字或特殊字符系统,则可以利用给定的 version 来帮助确定后续值。

另请参阅

不特定后端的 GUID 类型

服务器端版本计数器

version_id_generator 也可以配置为依赖于数据库生成的值。在这种情况下,数据库需要在将行受到 INSERT 时以及 UPDATE 时生成新标识符的某种手段。对于 UPDATE 情况,通常需要一个更新触发器,除非所涉及的数据库支持其他本地版本标识符。特别是,PostgreSQL 数据库支持一个名为 xmin 的系统列,提供 UPDATE 版本控制。我们可以利用 PostgreSQL 的 xmin 列来为我们的 User 类进行版本控制,如下所示:

代码语言:javascript复制
from sqlalchemy import FetchedValue

class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    name = mapped_column(String(50), nullable=False)
    xmin = mapped_column("xmin", String, system=True, server_default=FetchedValue())

    __mapper_args__ = {"version_id_col": xmin, "version_id_generator": False}

使用上述映射,ORM 将依赖于 xmin 列来自动提供版本 ID 计数器的新值。

当 ORM 发出 INSERT 或 UPDATE 时,通常不会主动获取数据库生成的值的值,而是将这些列保留为“过期”,并在下次访问它们时获取,除非设置了 eager_defaults Mapper 标志。然而,当使用服务器端版本列时,ORM 需要主动获取新生成的值。这是为了在任何并发事务可能再次更新它之前设置版本计数器。最好在 INSERT 或 UPDATE 语句中同时进行这个获取,使用 RETURNING,否则,如果之后发出一个 SELECT 语句,那么版本计数器在它被获取之前可能会发生竞争条件。

当目标数据库支持 RETURNING 时,我们的 User 类的 INSERT 语句将如下所示:

代码语言:javascript复制
INSERT  INTO  "user"  (name)  VALUES  (%(name)s)  RETURNING  "user".id,  "user".xmin
-- {'name': 'ed'}

在上述情况下,ORM 可以在一个语句中获取任何新生成的主键值以及服务器生成的版本标识符。当后端不支持 RETURNING 时,必须为每个 INSERT 和 UPDATE 发出额外的 SELECT,这非常低效,还会引入遗漏版本计数器的可能性:

代码语言:javascript复制
INSERT  INTO  "user"  (name)  VALUES  (%(name)s)
-- {'name': 'ed'}

SELECT  "user".version_id  AS  user_version_id  FROM  "user"  where
"user".id  =  :param_1
-- {"param_1": 1}

仅在绝对必要时,并且仅在支持返回的后端上,强烈建议仅使用服务器端版本计数器,目前支持的后端有 PostgreSQL、Oracle、MariaDB 10.5、SQLite 3.35 和 SQL Server。

编程或有条件的版本计数器

version_id_generator 设置为 False 时,我们也可以以编程方式(并有条件地)像分配任何其他映射属性一样,在对象上设置版本标识符。例如,如果我们使用了 UUID 示例,但将 version_id_generator 设置为 False,我们可以根据自己的需要设置版本标识符:

代码语言:javascript复制
import uuid

class User(Base):
    __tablename__ = "user"

    id = mapped_column(Integer, primary_key=True)
    version_uuid = mapped_column(String(32), nullable=False)
    name = mapped_column(String(50), nullable=False)

    __mapper_args__ = {"version_id_col": version_uuid, "version_id_generator": False}

u1 = User(name="u1", version_uuid=uuid.uuid4())

session.add(u1)

session.commit()

u1.name = "u2"
u1.version_uuid = uuid.uuid4()

session.commit()

我们还可以在不递增版本计数器的情况下更新我们的 User 对象;计数器的值将保持不变,并且 UPDATE 语句仍将根据先前的值进行检查。这在仅特定类的 UPDATE 对并发问题敏感的方案中可能很有用:

代码语言:javascript复制
# will leave version_uuid unchanged
u1.name = "u3"
session.commit()

类映射 API

原文:docs.sqlalchemy.org/en/20/orm/mapping_api.html

对象名称

描述

add_mapped_attribute(target, key, attr)

向 ORM 映射类添加新的映射属性。

as_declarative(**kw)

类装饰器,将给定的类适配为declarative_base()。

class_mapper(class_[, configure])

给定一个类,返回与该键关联的主要Mapper。

clear_mappers()

从所有类中删除所有映射器。

column_property(column, *additional_columns, [group, deferred, raiseload, comparator_factory, init, repr, default, default_factory, compare, kw_only, active_history, expire_on_flush, info, doc])

为映射提供列级别属性。

configure_mappers()

初始化到目前为止已在所有registry集合中构造的所有映射器之间的相互关系。

declarative_base(*, [metadata, mapper, cls, name, class_registry, type_annotation_map, constructor, metaclass])

构造用于声明性类定义的基类。

declarative_mixin(cls)

将类标记为提供“声明混入”功能。

DeclarativeBase

用于声明性类定义的基类。

DeclarativeBaseNoMeta

与DeclarativeBase相同,但不使用元类拦截新属性。

declared_attr

将类级别方法标记为表示映射属性或声明式指令定义的方法。

has_inherited_table(cls)

给定一个类,如果它继承的任何类都有映射表,则返回 True,否则返回 False。

identity_key([class_, ident], *, [instance, row, identity_token])

生成“标识键”元组,这些元组用作Session.identity_map 字典中的键。

mapped_column([__name_pos, _type_pos], *args, [init, repr, default, default_factory, compare, kw_only, nullable, primary_key, deferred, deferred_group, deferred_raiseload, use_existing_column, name, type, autoincrement, doc, key, index, unique, info, onupdate, insert_default, server_default, server_onupdate, active_history, quote, system, comment, sort_order], **kw)

在 声明式表 配置中声明一个新的 ORM 映射的 Column 构造。

MappedAsDataclass

用于指示映射此类时,同时将其转换为数据类的混合类。

MappedClassProtocol

表示 SQLAlchemy 映射类的协议。

Mapper

定义 Python 类与数据库表或其他关系结构之间的关联,以便对该类进行的 ORM 操作可以继续进行。

object_mapper(instance)

给定一个对象,返回与对象实例关联的主要 Mapper。

orm_insert_sentinel([name, type_], *, [default, omit_from_statements])

提供一个替代 mapped_column() 的代理,生成所谓的 sentinel 列,允许在其他情况下没有符合条件的主键配置的表中进行高效的批量插入,并且具有确定性的 RETURNING 排序。

polymorphic_union(table_map, typecolname[, aliasname, cast_nulls])

创建多态映射器使用的 UNION 语句。

reconstructor(fn)

将方法装饰为 ‘reconstructor’ 钩子。

注册表

用于映射类的通用注册表。

synonym_for(name[, map_column])

与 Python 描述符一起生成一个 synonym() 属性的装饰器。

代码语言:javascript复制
class sqlalchemy.orm.registry

用于映射类的通用注册表。

registry 用作维护映射集合的基础,并提供用于映射类的配置钩子。

支持的三种常规映射类型是声明基类(Declarative Base)、声明装饰器(Declarative Decorator)和命令式映射(Imperative Mapping)。所有这些映射样式都可以互换使用:

  • registry.generate_base() 返回一个新的声明基类,是 declarative_base() 函数的底层实现。
  • registry.mapped() 提供了一个类装饰器,它将为一个类应用声明性映射,而不使用声明性基类。
  • registry.map_imperatively() 会为一个类生成一个 Mapper,而不会扫描该类以寻找声明性类属性。这种方法适用于历史上由 sqlalchemy.orm.mapper() 传统映射函数提供的用例,该函数已在 SQLAlchemy 2.0 中移除。

从版本 1.4 新增。

成员

init(), as_declarative_base(), configure(), dispose(), generate_base(), map_declaratively(), map_imperatively(), mapped(), mapped_as_dataclass(), mappers, update_type_annotation_map()

参见

ORM 映射类概述 - 类映射样式概述。

代码语言:javascript复制
method __init__(*, metadata: Optional[MetaData] = None, class_registry: Optional[clsregistry._ClsRegistryType] = None, type_annotation_map: Optional[_TypeAnnotationMapType] = None, constructor: Callable[..., None] = <function _declarative_constructor>)

构建一个新的 registry

参数:

  • metadata – 一个可选的 MetaData 实例。使用声明性表映射生成的所有 Table 对象将使用此 MetaData 集合。如果将此参数保留在默认值 None,则会创建一个空白的 MetaData 集合。
  • constructor – 指定在没有自己的 __init__ 的映射类上的 __init__ 函数的实现。默认情况下,为声明的字段和关系分配 **kwargs 的实现分配给一个实例。如果提供 None,则不会提供 init,并且构造将回退到 cls.init 的普通 Python 语义。
  • class_registry – 可选的字典,当使用字符串名称来标识 relationship() 等内部类时,将充当类名称->映射类的注册表。允许两个或更多声明性基类共享相同的类名称注册表,以简化基类之间的关系。
  • type_annotation_map – 可选的 Python 类型到 SQLAlchemy TypeEngine类或实例的字典。提供的字典将更新默认类型映射。这仅由MappedColumn构造在Mapped类型内部的注解产生列类型时使用。 新版本 2.0 中的内容。 另请参阅 自定义类型映射
代码语言:javascript复制
method as_declarative_base(**kw: Any) → Callable[[Type[_T]], Type[_T]]

类装饰器,将为给定的基类调用registry.generate_base()

例如:

代码语言:javascript复制
from sqlalchemy.orm import registry

mapper_registry = registry()

@mapper_registry.as_declarative_base()
class Base:
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id = Column(Integer, primary_key=True)

class MyMappedClass(Base):
    # ...

所有传递给registry.as_declarative_base()的关键字参数都会传递给registry.generate_base()

代码语言:javascript复制
method configure(cascade: bool = False) → None

配置此注册表中所有尚未配置的映射器。

配置步骤用于调和和初始化relationship()链接,以及调用配置事件,如MapperEvents.before_configured()MapperEvents.after_configured(),这些事件可以被 ORM 扩展或用户定义的扩展钩子所使用。

如果此注册表中的一个或多个映射器包含指向其他注册表中映射类的relationship()构造,则称该注册表为依赖于那些注册表。为了自动配置这些依赖注册表,configure.cascade标志应设置为True。否则,如果它们未配置,则会引发异常。此行为背后的原理是允许应用程序在控制是否隐式到达其他注册表的同时,以编程方式调用注册表的配置。

作为调用registry.configure()的替代方案,可以使用 ORM 函数configure_mappers()函数确保内存中所有registry对象的配置完成。这通常更简单,并且还早于整体使用registry对象的用法。但是,此函数将影响运行中的 Python 进程中的所有映射,并且对于具有许多用于不同目的的注册表的应用程序可能更耗费内存/时间,这些注册表可能不会立即需要。

另请参阅

configure_mappers()

自版本 1.4.0b2 新增。

代码语言:javascript复制
method dispose(cascade: bool = False) → None

处理此 registry 中的所有映射器。

调用后,此注册表中映射的所有类将不再具有与类相关联的类仪器。该方法是每个registry的类似于应用程序范围的clear_mappers()函数。

如果此注册表包含其他注册表的依赖项映射器,通常通过relationship()链接,则必须将这些注册表也处理掉。当这些注册表存在于与此相关的关系中时,如果设置了dispose.cascade标志为True,则它们的registry.dispose()方法也将被调用;否则,如果这些注册表尚未被处理,则会引发错误。

自版本 1.4.0b2 新增。

另请参阅

clear_mappers()

代码语言:javascript复制
method generate_base(mapper: ~typing.Callable[[...], ~sqlalchemy.orm.mapper.Mapper[~typing.Any]] | None = None, cls: ~typing.Type[~typing.Any] = <class 'object'>, name: str = 'Base', metaclass: ~typing.Type[~typing.Any] = <class 'sqlalchemy.orm.decl_api.DeclarativeMeta'>) → Any

生成一个声明性基类。

继承自返回的类对象的类将使用声明性映射自动映射。

例如:

代码语言:javascript复制
from sqlalchemy.orm import registry

mapper_registry = registry()

Base = mapper_registry.generate_base()

class MyClass(Base):
    __tablename__ = "my_table"
    id = Column(Integer, primary_key=True)

上述动态生成的类等同于下面的非动态示例:

代码语言:javascript复制
from sqlalchemy.orm import registry
from sqlalchemy.orm.decl_api import DeclarativeMeta

mapper_registry = registry()

class Base(metaclass=DeclarativeMeta):
    __abstract__ = True
    registry = mapper_registry
    metadata = mapper_registry.metadata

    __init__ = mapper_registry.constructor

自版本 2.0 变更:请注意,registry.generate_base()方法已被新的DeclarativeBase类取代,该类使用子类化生成一个新的“基”类,而不是函数的返回值。这样可以与PEP 484类型工具兼容的方法。

registry.generate_base()方法提供了declarative_base()函数的实现,该函数一次性创建了registry和基类。

查看声明式映射部分以获取背景和示例。

参数:

  • mapper – 可选可调用对象,默认为Mapper。此函数用于生成新的Mapper对象。
  • cls – 默认为object。要用作生成的声明性基类的基础的类型。可以是类或类的元组。
  • name – 默认为Base。生成类的显示名称。虽然不需要自定义此项,但可以提高回溯和调试时的清晰度。
  • metaclass – 默认为DeclarativeMeta。作为生成的声明性基类的元类型的元类或__metaclass__兼容可调用对象。

另请参阅

声明式映射

declarative_base()

代码语言:javascript复制
method map_declaratively(cls: Type[_O]) → Mapper[_O]

声明性地映射一个类。

在这种映射形式中,将扫描类以获取映射信息,包括要与表关联的列和/或实际表对象。

返回Mapper对象。

例如:

代码语言:javascript复制
from sqlalchemy.orm import registry

mapper_registry = registry()

class Foo:
    __tablename__ = 'some_table'

    id = Column(Integer, primary_key=True)
    name = Column(String)

mapper = mapper_registry.map_declaratively(Foo)

此函数更方便地通过registry.mapped()类装饰器或通过从registry.generate_base()生成的声明性元类的子类间接调用。

查看完整详情和示例,请参阅声明式映射部分。

参数:

cls – 要映射的类。

返回:

一个Mapper对象。

另请参阅

声明式映射

registry.mapped() - 更常见的此函数的装饰器接口。

registry.map_imperatively()

代码语言:javascript复制
method map_imperatively(class_: Type[_O], local_table: FromClause | None = None, **kw: Any) → Mapper[_O]

命令式地映射一个类。

在这种映射形式中,不会扫描类以获取任何映射信息。相反,所有映射构造都作为参数传递。

此方法旨在与现在已删除的 SQLAlchemy mapper()函数完全等效,只是以特定注册表的术语表示。

例如:

代码语言:javascript复制
from sqlalchemy.orm import registry

mapper_registry = registry()

my_table = Table(
    "my_table",
    mapper_registry.metadata,
    Column('id', Integer, primary_key=True)
)

class MyClass:
    pass

mapper_registry.map_imperatively(MyClass, my_table)

查看完整背景和用法示例,请参阅命令式映射部分。

参数:

  • class_ – 要映射的类。对应于Mapper.class_参数。
  • local_table – 映射的主题是Table或其他FromClause对象。对应于Mapper.local_table参数。
  • **kw – 所有其他关键字参数直接传递给Mapper构造函数。

另请参见

命令式映射

声明式映射

代码语言:javascript复制
method mapped(cls: Type[_O]) → Type[_O]

类装饰器,将声明式映射过程应用于给定的类。

例如:

代码语言:javascript复制
from sqlalchemy.orm import registry

mapper_registry = registry()

@mapper_registry.mapped
class Foo:
    __tablename__ = 'some_table'

    id = Column(Integer, primary_key=True)
    name = Column(String)

参见声明式映射部分,获取完整的细节和示例。

参数:

cls – 要映射的类。

返回:

传递的类。

另请参见

声明式映射

registry.generate_base() - 生成一个基类,将自动对子类应用声明式映射,使用 Python 元类。

另请参见

registry.mapped_as_dataclass()

代码语言:javascript复制
method mapped_as_dataclass(_registry__cls: Type[_O] | None = None, *, init: _NoArg | bool = _NoArg.NO_ARG, repr: _NoArg | bool = _NoArg.NO_ARG, eq: _NoArg | bool = _NoArg.NO_ARG, order: _NoArg | bool = _NoArg.NO_ARG, unsafe_hash: _NoArg | bool = _NoArg.NO_ARG, match_args: _NoArg | bool = _NoArg.NO_ARG, kw_only: _NoArg | bool = _NoArg.NO_ARG, dataclass_callable: _NoArg | Callable[..., Type[Any]] = _NoArg.NO_ARG) → Type[_O] | Callable[[Type[_O]], Type[_O]]

类装饰器,将声明式映射过程应用于给定的类,并将类转换为 Python 数据类。

另请参见

声明式数据类映射 - SQLAlchemy 原生数据类映射的完整背景

版本 2.0 中的新功能。

代码语言:javascript复制
attribute mappers

所有Mapper对象的只读集合。

代码语言:javascript复制
method update_type_annotation_map(type_annotation_map: _TypeAnnotationMapType) → None

使用新值更新registry.type_annotation_map

代码语言:javascript复制
function sqlalchemy.orm.add_mapped_attribute(target: Type[_O], key: str, attr: MapperProperty[Any]) → None

向 ORM 映射类添加新的映射属性。

例如:

代码语言:javascript复制
add_mapped_attribute(User, "addresses", relationship(Address))

这可用于未使用截获属性设置操作的声明性元类的 ORM 映射。

版本 2.0 中的新功能。

代码语言:javascript复制
function sqlalchemy.orm.column_property(column: _ORMColumnExprArgument[_T], *additional_columns: _ORMColumnExprArgument[Any], group: str | None = None, deferred: bool = False, raiseload: bool = False, comparator_factory: Type[PropComparator[_T]] | None = None, init: _NoArg | bool = _NoArg.NO_ARG, repr: _NoArg | bool = _NoArg.NO_ARG, default: Any | None = _NoArg.NO_ARG, default_factory: _NoArg | Callable[[], _T] = _NoArg.NO_ARG, compare: _NoArg | bool = _NoArg.NO_ARG, kw_only: _NoArg | bool = _NoArg.NO_ARG, active_history: bool = False, expire_on_flush: bool = True, info: _InfoType | None = None, doc: str | None = None) → MappedSQLExpression[_T]

为映射提供列级属性。

使用声明式映射时,column_property()用于将只读的 SQL 表达式映射到映射类。

使用命令式映射时,column_property()还承担了将表列与附加功能进行映射的角色。使用完全声明式映射时,应使用mapped_column()构造来实现此目的。

在声明式数据类映射中,column_property() 被认为是只读的,并且不会包含在数据类的 __init__() 构造函数中。

column_property() 函数返回 ColumnProperty 的实例。

另请参阅

使用 column_property - 通常使用 column_property() 来映射 SQL 表达式。

对命令式表列应用加载、持久化和映射选项 - 使用column_property()与命令式表映射,将附加选项应用到普通Column对象的用法。

参数:

  • *cols – 要映射的列对象列表。
  • active_history=False – 仅用于命令式表映射,或遗留式声明式映射(即尚未升级为mapped_column()的映射),用于预期可写的基于列的属性;对于声明式映射,请使用 mapped_column()mapped_column.active_history。有关功能细节,请参阅该参数。
  • comparator_factory – 一个继承自Comparator的类,提供比较操作的自定义 SQL 子句生成。
  • group – 当标记为延迟加载时,此属性的组名称。
  • deferred – 当为 True 时,列属性是“延迟加载”的,这意味着它不会立即加载,而是在首次在实例上访问属性时加载。另请参阅 deferred()
  • doc – 可选字符串,将应用于类绑定的描述符的文档。
  • expire_on_flush=True – 禁用刷新时的过期。引用 SQL 表达式(而不是单个表绑定列)的 column_property() 被视为“只读”属性;填充它对数据状态没有影响,它只能返回数据库状态。因此,每当父对象涉及到刷新时,即在刷新中具有任何类型的“脏”状态时,都会过期 column_property() 的值。将此参数设置为 False 将导致在刷新继续进行后保留任何现有值。请注意,默认过期设置的 Session 仍在 Session.commit() 调用后过期所有属性,但是。
  • info – 可选数据字典,将填充到此对象的 MapperProperty.info 属性中。
  • raiseload – 如果为 True,则表示在未延迟加载列时应引发错误,而不是加载值。可以通过在查询时使用带有 raiseload=False 的 deferred() 选项来更改此行为。 从版本 1.4 开始新增。 另请参阅 使用 raiseload 避免延迟列加载
  • init – 自版本 1.4 起弃用:column_property.init 参数对于 column_property() 已弃用。此参数仅适用于声明性数据类配置中的可写属性,而 column_property() 在此上下文中被视为只读属性。
  • default – 自版本 1.4 起弃用:column_property.default 参数对于 column_property() 已弃用。此参数仅适用于声明性数据类配置中的可写属性,而 column_property() 在此上下文中被视为只读属性。
  • default_factory – 自 1.4 版本起弃用:column_property.default_factory 参数已弃用于 column_property()。此参数仅适用于声明性数据类配置中的可写属性,而在此上下文中,column_property() 被视为只读属性。
  • kw_only – 自 1.4 版本起弃用:column_property.kw_only 参数已弃用于 column_property()。此参数仅适用于声明性数据类配置中的可写属性,而在此上下文中,column_property() 被视为只读属性。
代码语言:javascript复制
function sqlalchemy.orm.declarative_base(*, metadata: Optional[MetaData] = None, mapper: Optional[Callable[..., Mapper[Any]]] = None, cls: Type[Any] = <class 'object'>, name: str = 'Base', class_registry: Optional[clsregistry._ClsRegistryType] = None, type_annotation_map: Optional[_TypeAnnotationMapType] = None, constructor: Callable[..., None] = <function _declarative_constructor>, metaclass: Type[Any] = <class 'sqlalchemy.orm.decl_api.DeclarativeMeta'>) → Any

构建用于声明性类定义的基类。

新的基类将被赋予一个元类,该元类生成适当的 Table 对象,并根据在类及其任何子类中声明的信息进行适当的 Mapper 调用。

在 2.0 版本中更改:注意 declarative_base() 函数已被新的 DeclarativeBase 类所取代,该类使用子类化生成一个新的“基”类,而不是一个函数的返回值。这允许与 PEP 484 类型工具兼容的方法。

declarative_base() 函数是使用 registry.generate_base() 方法的简写版本。即:

代码语言:javascript复制
from sqlalchemy.orm import declarative_base

Base = declarative_base()

等同于:

代码语言:javascript复制
from sqlalchemy.orm import registry

mapper_registry = registry()
Base = mapper_registry.generate_base()

查看 registryregistry.generate_base() 的文档字符串以获取更多细节。

在 1.4 版本中更改:declarative_base() 函数现在是更通用的 registry 类的特化版本。该函数还从 declarative.ext 包移动到 sqlalchemy.orm 包中。

参数:

  • metadata – 可选的MetaData实例。所有基类的子类隐式声明的所有Table对象将共享此 MetaData。如果未提供,则将创建一个 MetaData 实例。 MetaData 实例将通过生成的声明性基类的 metadata 属性可用。
  • mapper – 可选可调用项,默认为Mapper。将用于将子类映射到其表格。
  • cls – 默认为object。要用作生成的声明性基类的基类的类型。可以是一个类或类的元组。
  • name – 默认为Base。生成类的显示名称。不需要自定义此选项,但可以提高回溯和调试时的清晰度。
  • constructor – 指定在没有自己的__init__的映射类上实现__init__函数的实现。默认为一种实现,将声明的字段和关系的 **kwargs 分配给一个实例。如果提供了None,则不会提供__init__,并且构造将通过普通的 Python 语义回退到 cls.__init__
  • class_registry – 可选字典,将用作当使用字符串名称标识relationship()等内部的类时,类名->映射类的注册表。允许两个或更多声明性基类共享相同的类名注册表,以简化基类之间的关系。
  • type_annotation_map – Python 类型到 SQLAlchemy TypeEngine 类或实例的可选字典。这仅由MappedColumn构造用于基于Mapped类型中的注释生成列类型。 版本 2.0 中的新功能。 另请参见 自定义类型映射
  • metaclass – 默认为DeclarativeMeta。要用作生成的声明性基类的元类型的元类或__metaclass__兼容可调用项。

另请参见

registry

代码语言:javascript复制
function sqlalchemy.orm.declarative_mixin(cls: Type[_T]) → Type[_T]

将类标记为提供“声明性混合”的功能。

例如:

代码语言:javascript复制
from sqlalchemy.orm import declared_attr
from sqlalchemy.orm import declarative_mixin

@declarative_mixin
class MyMixin:

    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    __table_args__ = {'mysql_engine': 'InnoDB'}
    __mapper_args__= {'always_refresh': True}

    id =  Column(Integer, primary_key=True)

class MyModel(MyMixin, Base):
    name = Column(String(1000))

declarative_mixin() 装饰器当前不会以任何方式修改给定的类;其当前目的严格来说是帮助 Mypy 插件能够在没有其他上下文的情况下识别 SQLAlchemy 声明性混合类。

版本 1.4.6 中的新功能。

另请参阅

使用 Mixins 组合映射层次结构

使用 @declared_attr 和声明性 Mixins - 在 Mypy 插件文档中

代码语言:javascript复制
function sqlalchemy.orm.as_declarative(**kw: Any) → Callable[[Type[_T]], Type[_T]]

类装饰器,将给定的类适应为declarative_base()

此函数利用了registry.as_declarative_base()方法,首先自动创建一个registry,然后调用装饰器。

例如:

代码语言:javascript复制
from sqlalchemy.orm import as_declarative

@as_declarative()
class Base:
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id = Column(Integer, primary_key=True)

class MyMappedClass(Base):
    # ...

另请参阅

registry.as_declarative_base()

代码语言:javascript复制
function sqlalchemy.orm.mapped_column(__name_pos: str | _TypeEngineArgument[Any] | SchemaEventTarget | None = None, __type_pos: _TypeEngineArgument[Any] | SchemaEventTarget | None = None, *args: SchemaEventTarget, init: _NoArg | bool = _NoArg.NO_ARG, repr: _NoArg | bool = _NoArg.NO_ARG, default: Any | None = _NoArg.NO_ARG, default_factory: _NoArg | Callable[[], _T] = _NoArg.NO_ARG, compare: _NoArg | bool = _NoArg.NO_ARG, kw_only: _NoArg | bool = _NoArg.NO_ARG, nullable: bool | Literal[SchemaConst.NULL_UNSPECIFIED] | None = SchemaConst.NULL_UNSPECIFIED, primary_key: bool | None = False, deferred: _NoArg | bool = _NoArg.NO_ARG, deferred_group: str | None = None, deferred_raiseload: bool | None = None, use_existing_column: bool = False, name: str | None = None, type_: _TypeEngineArgument[Any] | None = None, autoincrement: _AutoIncrementType = 'auto', doc: str | None = None, key: str | None = None, index: bool | None = None, unique: bool | None = None, info: _InfoType | None = None, onupdate: Any | None = None, insert_default: Any | None = _NoArg.NO_ARG, server_default: _ServerDefaultArgument | None = None, server_onupdate: FetchedValue | None = None, active_history: bool = False, quote: bool | None = None, system: bool = False, comment: str | None = None, sort_order: _NoArg | int = _NoArg.NO_ARG, **kw: Any) → MappedColumn[Any]

为在声明性表配置中使用的新的 ORM 映射的Column构造声明。

mapped_column()函数提供了一个与 ORM 兼容且与 Python 类型兼容的构造,用于声明性映射,指示映射到 Core Column 对象的属性。当使用声明性时,特别是在使用声明性表配置时,它提供了将属性映射到Column对象的等效功能。

2.0 版中的新功能。

mapped_column()通常与显式类型一起使用,以及Mapped注释类型一起使用,它可以根据Mapped注释中的内容推导出列的 SQL 类型和可空性。它也可以在不带注释的情况下使用,作为 SQLAlchemy 1.x 风格中声明性映射中使用Column的替代品。

对于mapped_column()的使用示例,请参阅使用 mapped_column() 的声明性表中的文档。

另请参阅

使用 mapped_column() 的声明性表 - 完整文档

ORM 声明性模型 - 使用 1.x 风格映射的声明性映射的迁移说明

参数:

  • __name – 要为 Column 指定的字符串名称。这是一个可选的仅位置参数,如果存在,必须是传递的第一个位置参数。如果省略,则将使用 mapped_column() 映射到的属性名称作为 SQL 列名。
  • __typeTypeEngine 类型或实例,指示与 Column 关联的数据类型。这是一个可选的仅位置参数,如果存在,则必须紧随 __name 参数,否则必须是第一个位置参数。如果省略,则列的最终类型可以从注释类型中推导出,或者如果存在 ForeignKey,则可以从引用列的数据类型中推导出。
  • *args – 额外的位置参数包括诸如 ForeignKeyCheckConstraintIdentity 这样的结构,它们被传递到构造的 Column 中。
  • nullable – 可选布尔值,指示列是否应为“NULL”或“NOT NULL”。如果省略,nullability 将根据类型注释推导而来,根据 typing.Optional 是否存在而定。否则,对于非主键列,nullable 默认为 True,对于主键列,默认为 False
  • primary_key – 可选布尔值,表示 Column 是否将成为表的主键。
  • deferred – 可选布尔值 - 此关键字参数由 ORM 声明过程使用,并不是 Column 本身的一部分;相反,它表示此列应当被“延迟”加载,就好像被 deferred() 映射一样。 另请参阅 配置映射中的列延迟
  • deferred_group – 暗示将 mapped_column.deferred 设置为 True,并设置 deferred.group 参数。 另请参阅 以组加载延迟列
  • deferred_raiseload – 意味着将 mapped_column.deferred 设置为 True,并设置 deferred.raiseload 参数。 另请参阅 使用 raiseload 避免延迟加载列
  • use_existing_column – 如果为 True,则尝试在继承的超类(通常是单一继承的超类)上定位给定列名,如果存在,则不会生成新列,将映射到超类列,就好像该列从此类中省略一样。这用于将新列添加到继承的超类的混合类。 另请参阅 使用 use_existing_column 解决列冲突 从 2.0.0b4 版开始新增。
  • default – 如果 mapped_column.insert_default 参数不存在,则直接传递给 Column.default 参数。此外,在使用声明式数据类映射时,表示应该应用于生成的 __init__() 方法内的关键字构造函数的默认 Python 值。 请注意,在生成数据类时,当 mapped_column.insert_default 不存在时,这意味着 mapped_column.default 的值将在 两个 地方使用,即 __init__() 方法和 Column.default 参数。虽然此行为可能在将来的版本中更改,但目前这种情况通常“可以解决”;None 的默认值意味着 Column 不会得到默认生成器,而引用非None的默认值将在调用__init__()时提前分配给对象,在任何情况下,核心 Insert 构造将使用相同的值,从而导致相同的最终结果。 注意 当使用在 Core 级别的列默认值作为可调用对象,由底层Column与 ORM 映射的数据类,特别是那些是上下文感知的默认函数时,必须使用**mapped_column.insert_default参数**。这是必要的,以消除可调用对象被解释为数据类级别默认值的歧义。
  • insert_default – 直接传递给Column.default参数;当存在时,将取代mapped_column.default的值,但无论何时,mapped_column.default都将应用于数据类映射的构造函数默认值。
  • sort_order – 表示当 ORM 创建Table时,此映射列应如何与其他列排序的整数。对于具有相同值的映射列,默认使用默认排序,首先放置在主类中定义的映射列,然后放置在超类中的映射列。默认为 0。排序为升序。 版本 2.0.4 中的新内容。
  • active_history=False – 当True时,表示应在替换时加载标量属性的“上一个”值,如果尚未加载。通常,简单非主键标量值的历史跟踪逻辑只需要知道“新”值就能执行刷新。此标志适用于需要使用get_history()Session.is_modified()并且还需要知道属性的“上一个”值的应用程序。 版本 2.0.10 中的新内容。
  • init – 特定于声明性数据类映射,指定映射属性是否应作为数据类过程生成的__init__()方法的一部分。
  • repr – 特定于声明性数据类映射,指定映射属性是否应作为数据类过程生成的__repr__()方法的一部分。
  • default_factory – 特定于声明性数据类映射,指定作为数据类过程生成的__init__()方法的一部分的默认值生成函数。
  • compare – 特定于声明式数据类映射,指示在为映射类生成__eq__()__ne__()方法时,是否应包含此字段在比较操作中。 在版本 2.0.0b4 中新增。
  • kw_only – 特定于声明式数据类映射,指示在生成__init__()时,是否应将此字段标记为仅关键字。
  • **kw – 所有剩余的关键字参数都传递给Column的构造函数。
代码语言:javascript复制
class sqlalchemy.orm.declared_attr

将类级方法标记为表示映射属性或声明性指令定义。

declared_attr通常作为类级方法的装饰器应用,将属性转换为类似标量的属性,可以从未实例化的类中调用。声明性映射过程在扫描类时寻找这些declared_attr可调用对象,并假定任何标记为declared_attr的属性将是一个可调用对象,将生成特定于声明性映射或表配置的对象。

declared_attr通常适用于混入类,用于定义应用于类的不同实现者的关系。它还可以用于定义动态生成的列表达式和其他声明性属性。

示例:

代码语言:javascript复制
class ProvidesUserMixin:
    "A mixin that adds a 'user' relationship to classes."

    user_id: Mapped[int] = mapped_column(ForeignKey("user_table.id"))

    @declared_attr
    def user(cls) -> Mapped["User"]:
        return relationship("User")

当与__tablename__等声明性指令一起使用时,可以使用declared_attr.directive()修饰符,指示PEP 484类型工具,给定的方法不涉及Mapped属性:

代码语言:javascript复制
class CreateTableName:
    @declared_attr.directive
    def __tablename__(cls) -> str:
        return cls.__name__.lower()

declared_attr也可以直接应用于映射类,以允许在使用映射继承方案时,属性可以在子类上动态配置自身。下面说明了使用declared_attr创建为子类生成Mapper.polymorphic_identity参数的动态方案:

代码语言:javascript复制
class Employee(Base):
    __tablename__ = 'employee'

    id: Mapped[int] = mapped_column(primary_key=True)
    type: Mapped[str] = mapped_column(String(50))

    @declared_attr.directive
    def __mapper_args__(cls) -> Dict[str, Any]:
        if cls.__name__ == 'Employee':
            return {
                    "polymorphic_on":cls.type,
                    "polymorphic_identity":"Employee"
            }
        else:
            return {"polymorphic_identity":cls.__name__}

class Engineer(Employee):
    pass

declared_attr支持装饰使用@classmethod显式装饰的函数。从运行时的角度来看,这从未必要,但可能需要支持不认识已装饰函数具有类级行为的cls参数的PEP 484类型工具:

代码语言:javascript复制
class SomethingMixin:
    x: Mapped[int]
    y: Mapped[int]

    @declared_attr
    @classmethod
    def x_plus_y(cls) -> Mapped[int]:
        return column_property(cls.x   cls.y)

版本 2.0 中的新功能:- declared_attr可以容纳使用@classmethod装饰的函数,以帮助需要的PEP 484集成。

另见

通过混合组合映射层次结构 - 附带对declared_attr使用模式的背景说明的声明性混合文档。

成员

级联,指令

类签名

sqlalchemy.orm.declared_attr (sqlalchemy.orm.base._MappedAttribute, sqlalchemy.orm.decl_api._declared_attr_common)

代码语言:javascript复制
attribute cascading

declared_attr标记为级联。

这是一个特殊用途的修饰符,表明在映射继承场景中,列或基于 MapperProperty 的声明属性应该在映射的子类中独立配置。

警告

declared_attr.cascading修饰符有几个限制:

  • 标志only适用于在声明性混合类和__abstract__类上使用declared_attr;当直接在映射类上使用时,它目前没有任何效果。
  • 标志only仅适用于通常命名的属性,例如不是任何特殊下划线属性,例如__tablename__。在这些属性上它没有效果。
  • 当前标志不允许进一步覆盖类层次结构下游;如果子类尝试覆盖属性,则会发出警告并跳过覆盖的属性。这是一个希望在某些时候解决的限制。

下面,无论是MyClass还是MySubClass都将建立一个独特的id列对象:

代码语言:javascript复制
class HasIdMixin:
    @declared_attr.cascading
    def id(cls):
        if has_inherited_table(cls):
            return Column(ForeignKey("myclass.id"), primary_key=True)
        else:
            return Column(Integer, primary_key=True)

class MyClass(HasIdMixin, Base):
    __tablename__ = "myclass"
    # ...

class MySubClass(MyClass):
  """ """

    # ...

上述配置的行为是,MySubClass将引用其自己的id列以及MyClass下面命名为some_id的属性。

另见

声明性继承

使用 _orm.declared_attr() 生成特定表继承列

代码语言:javascript复制
attribute directive

declared_attr 标记为装饰声明性指令,如 __tablename____mapper_args__

declared_attr.directive 的目的严格是支持PEP 484类型工具,允许装饰的函数具有不使用 Mapped 通用类的返回类型,这在使用 declared_attr 用于列和映射属性时通常是不会发生的。在运行时,declared_attr.directive 返回未经修改的 declared_attr 类。

例如:

代码语言:javascript复制
class CreateTableName:
    @declared_attr.directive
    def __tablename__(cls) -> str:
        return cls.__name__.lower()

2.0 版本中的新功能。

另请参见

使用 Mixins 组合映射层次结构

declared_attr

代码语言:javascript复制
class sqlalchemy.orm.DeclarativeBase

用于声明性类定义的基类。

DeclarativeBase 允许以与类型检查器兼容的方式创建新的声明性基类:

代码语言:javascript复制
from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
    pass

上述 Base 类现在可用作新声明性映射的基类。超类利用 __init_subclass__() 方法设置新类,而不使用元类。

首次使用时,DeclarativeBase 类实例化一个新的 registry 用于与基类一起使用,假设未明确提供。DeclarativeBase 类支持类级属性,这些属性充当此注册表构建的参数;例如指示特定的 MetaData 集合以及 registry.type_annotation_map 的特定值:

代码语言:javascript复制
from typing_extensions import Annotated

from sqlalchemy import BigInteger
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase

bigint = Annotated[int, "bigint"]
my_metadata = MetaData()

class Base(DeclarativeBase):
    metadata = my_metadata
    type_annotation_map = {
        str: String().with_variant(String(255), "mysql", "mariadb"),
        bigint: BigInteger()
    }

可指定的类级属性包括:

参数:

  • metadata – 可选的MetaData 集合。如果自动构造了一个registry,则将使用该MetaData 集合来构造它。否则,本地的MetaData 集合将取代通过DeclarativeBase.registry 参数传递的现有registry 使用的集合。
  • type_annotation_map – 可选的类型注释映射,将传递给registry 作为registry.type_annotation_map.
  • registry – 直接提供预先存在的registry

2.0 版本中的新功能:添加了DeclarativeBase,以便可以以也被PEP 484类型检查器识别的方式构造声明性基类。因此,DeclarativeBase 和其他基于子类化的 API 应被视为取代先前的“由函数返回的类” API,即declarative_base()registry.generate_base(),其中返回的基类不能被类型检查器识别,除非使用插件。

init 行为

在普通的 Python 类中,类层次结构中基本的 __init__() 方法是 object.__init__(),不接受任何参数。然而,当首次声明DeclarativeBase子类时,如果没有已经存在的 __init__() 方法,该类将被赋予一个 __init__() 方法,该方法链接到registry.constructor 构造函数;这是通常的声明性构造函数,将关键字参数分配给实例的属性,假定这些属性在类级别已经建立(即已映射,或者与描述符链接)。这个构造函数永远不会被映射类直接访问,除非通过显式调用 super(),因为映射类本身会直接得到一个 __init__() 方法,该方法调用registry.constructor,所以在默认情况下独立于基本的 __init__() 方法的操作。

从版本 2.0.1 开始发生了变化:DeclarativeBase 现在具有默认构造函数,默认链接到 registry.constructor,以便调用 super().__init__() 可以访问此构造函数。先前,由于一个实现错误,这个默认构造函数丢失了,调用 super().__init__() 将会调用 object.__init__()

DeclarativeBase 子类也可以声明一个显式的 __init__() 方法,该方法将在此级别替代 registry.constructor 函数的使用:

代码语言:javascript复制
class Base(DeclarativeBase):
    def __init__(self, id=None):
        self.id = id

映射的类仍然不会隐式调用这个构造函数;只能通过调用 super().__init__() 来访问它:

代码语言:javascript复制
class MyClass(Base):
    def __init__(self, id=None, name=None):
        self.name = name
        super().__init__(id=id)

请注意,这与诸如传统的 declarative_base() 等函数的行为不同;由这些函数创建的基类将始终为 __init__() 安装 registry.constructor

成员

mapper, mapper_args, table, table_args, tablename, metadata, registry

类签名

sqlalchemy.orm.DeclarativeBase (sqlalchemy.inspection.Inspectable)

代码语言:javascript复制
attribute __mapper__: ClassVar[Mapper[Any]]

将特定类映射到的 Mapper 对象。

也可以使用 inspect() 获取,例如 inspect(klass)

代码语言:javascript复制
attribute __mapper_args__: Any

传递给 Mapper 构造函数的参数字典。

另见

使用声明式的 Mapper 配置选项

代码语言:javascript复制
attribute __table__: ClassVar[FromClause]

将特定子类映射到的 FromClause

这通常是 Table 的一个实例,但根据类的映射方式,也可能是其他类型的 FromClause,比如 Subquery

另见

访问表和元数据

代码语言:javascript复制
attribute __table_args__: Any

将传递给Table构造函数的参数字典或元组。有关此集合特定结构的背景,请参阅声明式表配置。

另请参阅

声明式表配置

代码语言:javascript复制
attribute __tablename__: Any

将生成的Table对象分配的字符串名称,如果没有通过DeclarativeBase.__table__直接指定。

另请参阅

使用 mapped_column()的声明式表

代码语言:javascript复制
attribute metadata: ClassVar[MetaData]

指的是将用于新Table对象的MetaData集合。

另请参阅

访问表和元数据

代码语言:javascript复制
attribute registry: ClassVar[registry]

指的是新Mapper对象将关联的正在使用的registry

代码语言:javascript复制
class sqlalchemy.orm.DeclarativeBaseNoMeta

DeclarativeBase相同,但不使用元类拦截新属性。

当希望使用自定义元类时,可以使用DeclarativeBaseNoMeta基类。

2.0 版本中的新功能。

成员

mapper, mapper_args, table, table_args, tablename, metadata, registry

类签名

sqlalchemy.orm.DeclarativeBaseNoMeta (sqlalchemy.inspection.Inspectable)

代码语言:javascript复制
attribute __mapper__: ClassVar[Mapper[Any]]

将特定类映射到的Mapper对象。

也可以使用inspect()获得,例如inspect(klass)

代码语言:javascript复制
attribute __mapper_args__: Any

将传递给Mapper构造函数的参数字典。

另请参阅

使用声明式的 Mapper 配置选项

代码语言:javascript复制
attribute __table__: FromClause | None

将特定子类映射到的FromClause

这通常是Table的实例,但根据类的映射方式,也可能引用其他类型的FromClause,例如Subquery

另请参阅

访问表和元数据

代码语言:javascript复制
attribute __table_args__: Any

将传递给Table构造函数的参数字典或元组。有关此集合特定结构的背景,请参阅声明式表配置。

另请参阅

声明式表配置

代码语言:javascript复制
attribute __tablename__: Any

分配给生成的Table对象的字符串名称,如果未直接通过DeclarativeBase.__table__指定。

另请参阅

具有 mapped_column()的声明式表

代码语言:javascript复制
attribute metadata: ClassVar[MetaData]

指的是将用于新Table对象的MetaData集合。

另请参阅

访问表和元数据

代码语言:javascript复制
attribute registry: ClassVar[registry]

指的是新的Mapper对象将与之关联的正在使用的registry

代码语言:javascript复制
function sqlalchemy.orm.has_inherited_table(cls: Type[_O]) → bool

给定一个类,如果它继承的任何类都有一个映射表,则返回 True,否则返回 False。

这在声明式混合中用于构建在继承层次结构中的基类和子类之间行为不同的属性。

另请参阅

使用混合和基类进行映射继承模式

代码语言:javascript复制
function sqlalchemy.orm.synonym_for(name: str, map_column: bool = False) → Callable[[Callable[[...], Any]], Synonym[Any]]

在与 Python 描述符一起生成synonym()属性的装饰器。

被装饰的函数将被传递给synonym()作为synonym.descriptor参数:

代码语言:javascript复制
class MyClass(Base):
    __tablename__ = 'my_table'

    id = Column(Integer, primary_key=True)
    _job_status = Column("job_status", String(50))

    @synonym_for("job_status")
    @property
    def job_status(self):
        return "Status: %s" % self._job_status

SQLAlchemy 的混合属性功能通常比同义词更受青睐,后者是一个更传统的功能。

另请参阅

同义词 - 同义词概述

synonym() - 映射器级函数

使用描述符和混合属性 - Hybrid Attribute 扩展提供了一种更新的方法来更灵活地增强属性行为,比使用同义词更容易实现。

代码语言:javascript复制
function sqlalchemy.orm.object_mapper(instance: _T) → Mapper[_T]

给定一个对象,返回与该对象实例关联的主要映射器。

如果没有配置映射,则引发sqlalchemy.orm.exc.UnmappedInstanceError

此功能可通过检查系统使用:

代码语言:javascript复制
inspect(instance).mapper

如果实例不是映射的一部分,则使用检查系统将引发sqlalchemy.exc.NoInspectionAvailable

代码语言:javascript复制
function sqlalchemy.orm.class_mapper(class_: Type[_O], configure: bool = True) → Mapper[_O]

给定一个类,返回与该键关联的主要Mapper

如果给定类上没有配置映射,则引发UnmappedClassError,或者如果传递了非类对象,则引发ArgumentError

相当的功能可以通过inspect()函数实现:

代码语言:javascript复制
inspect(some_mapped_class)

如果类未映射,则使用检查系统将引发sqlalchemy.exc.NoInspectionAvailable

代码语言:javascript复制
function sqlalchemy.orm.configure_mappers() → None

初始化到目前为止在所有registry集合中已构建的所有映射器的互映关系。

配置步骤用于协调和初始化映射类之间的relationship()链接,以及调用配置事件,如MapperEvents.before_configured()MapperEvents.after_configured(),这些事件可能被 ORM 扩展或用户定义的扩展钩子使用。

映射器配置通常是自动调用的,第一次使用特定 registry 的映射时,以及每当使用映射并且已经构造了额外的尚未配置的映射器时。然而,自动配置过程仅局限于涉及目标映射器和任何相关的 registry 对象的 registry;这相当于在特定 registry 上调用 registry.configure() 方法。

与之相比,configure_mappers() 函数将在内存中存在的所有 registry 对象上调用配置过程,并且可能对使用许多个体 registry 对象但彼此相关的场景有用。

从版本 1.4 开始更改:从 SQLAlchemy 1.4.0b2 开始,此函数按照每个 registry 的方式工作,定位所有存在的 registry 对象并调用每个对象上的 registry.configure() 方法。可能更喜欢使用 registry.configure() 方法来限制映射器的配置仅限于特定 registry 和/或声明性基类。

自动配置被调用的点包括当映射类被实例化为实例时,以及当使用 Session.query()Session.execute() 发出 ORM 查询时使用 ORM 启用的语句。

映射器配置过程,无论是由 configure_mappers() 还是 registry.configure() 调用,都提供了几个可用于增强映射器配置步骤的事件挂钩。这些挂钩包括:

  • MapperEvents.before_configured() - 在 configure_mappers()registry.configure() 执行任何工作之前调用一次;这可用于在操作继续之前建立其他选项、属性或相关映射。
  • MapperEvents.mapper_configured() - 在进程中配置每个单独的 Mapper 时调用;将包括除其他映射器设置的反向引用之外的所有映射器状态,这些映射器尚未配置。
  • MapperEvents.after_configured() - 在 configure_mappers()registry.configure() 完成后调用一次;在此阶段,所有配置操作范围内的 Mapper 对象将被完全配置。请注意,调用应用程序可能仍然有其他尚未生成的映射,例如,如果它们在尚未导入的模块中,还可能有映射尚未配置,如果它们位于当前配置范围之外的其他registry集合中。
代码语言:javascript复制
function sqlalchemy.orm.clear_mappers() → None

删除所有类的所有映射器。

从版本 1.4 开始变更:这个函数现在定位所有的registry对象,并调用每个对象的 registry.dispose() 方法。

这个函数从类中删除所有的仪器,并处置它们的关联映射器。一旦调用,这些类将被取消映射,以后可以用新的映射器重新映射。

clear_mappers() 是正常使用,因为在非常特定的测试场景之外,它实际上没有任何有效用途。通常,映射器是用户定义类的永久结构组件,绝不会独立于其类被丢弃。如果映射类本身被垃圾回收,其映射器也将被自动处理。因此,clear_mappers() 仅用于在测试套件中重复使用相同类的不同映射的情况下,这本身是一个极为罕见的用例 - 唯一的这种用例实际上是 SQLAlchemy 自己的测试套件,可能是其他 ORM 扩展库的测试套件,这些库打算在一组固定的类上测试各种映射构造的组合。

代码语言:javascript复制
function sqlalchemy.orm.util.identity_key(class_: Type[_T] | None = None, ident: Any | Tuple[Any, ...] = None, *, instance: _T | None = None, row: Row[Any] | RowMapping | None = None, identity_token: Any | None = None) → _IdentityKeyType[_T]

生成“标识键”元组,用作 Session.identity_map 字典中的键。

此函数有几种调用样式:

identity_key(class, ident, identity_token=token)

此形式接收一个映射类和一个主键标量或元组作为参数。

例如:

代码语言:javascript复制
>>> identity_key(MyClass, (1, 2))
(<class '__main__.MyClass'>, (1, 2), None)

参数类:

映射类(必须是一个位置参数)

参数 ident:

主键,可以是标量或元组参数。

参数 identity_token:

可选的标识令牌

版本 1.2 中的新功能:添加了 identity_token

identity_key(instance=instance)

此形式将为给定实例生成标识键。实例不必是持久的,只需其主键属性被填充(否则键将包含这些缺失值的 None)。

例如:

代码语言:javascript复制
>>> instance = MyClass(1, 2)
>>> identity_key(instance=instance)
(<class '__main__.MyClass'>, (1, 2), None)

在此形式中,给定实例最终将通过 Mapper.identity_key_from_instance() 运行,如果对象已过期,则将执行相应行的数据库检查。

参数实例:

对象实例(必须作为关键字参数给出)

identity_key(class, row=row, identity_token=token)

此形式类似于类/元组形式,但是传递了数据库结果行作为 RowRowMapping 对象。

例如:

代码语言:javascript复制
>>> row = engine.execute(
 text("select * from table where a=1 and b=2")
 ).first()
>>> identity_key(MyClass, row=row)
(<class '__main__.MyClass'>, (1, 2), None)

参数类:

映射类(必须是一个位置参数)

参数行:

RowCursorResult 返回的行(必须作为关键字参数给出)

参数 identity_token:

可选的标识令牌

版本 1.2 中的新功能:添加了 identity_token

代码语言:javascript复制
function sqlalchemy.orm.polymorphic_union(table_map, typecolname, aliasname='p_union', cast_nulls=True)

创建一个多态映射器使用的 UNION 语句。

请参见具体表继承以了解如何使用此功能。

参数:

  • table_map – 将多态标识映射到 Table 对象。
  • typecolname – “鉴别器”列的字符串名称,该列将从查询中派生,为每一行产生多态标识。如果为 None,则不生成多态鉴别器。
  • aliasname – 生成的 alias() 构造的名称。
  • cast_nulls – 如果为 True,则不存在的列,表示为标记的 NULL 值,将被传递到 CAST 中。这是一种问题的传统行为,对于某些后端(如 Oracle)存在问题 - 在这种情况下,可以将其设置为 False。
代码语言:javascript复制
function sqlalchemy.orm.orm_insert_sentinel(name: str | None = None, type_: _TypeEngineArgument[Any] | None = None, *, default: Any | None = None, omit_from_statements: bool = True) → MappedColumn[Any]

提供了一个虚拟的 mapped_column(),它生成所谓的 sentinel 列,允许对于不具有合格的主键配置的表进行具有确定性的 RETURNING 排序的高效批量插入。

使用orm_insert_sentinel()类似于在 Core Table 构造中使用insert_sentinel() 构造的用法。

将此构造添加到声明式映射类的指南与insert_sentinel() 构造的相同;数据库表本身也需要具有此名称的列。

关于此对象的使用背景,请参阅 配置 Sentinel 列 作为 “INSERT 语句的“插入多个值”行为 部分的一部分。

另请参见

insert_sentinel()

“INSERT 语句的“插入多个值”行为

配置 Sentinel 列

2.0.10 版本中的新增内容。

代码语言:javascript复制
function sqlalchemy.orm.reconstructor(fn)

将一个方法装饰为‘reconstructor’挂钩。

将单个方法指定为“reconstructor”,一个类似于__init__方法的方法,ORM 在实例从数据库中加载或者以其他方式重新构建后会调用该方法。

提示

reconstructor() 装饰器使用了 InstanceEvents.load() 事件挂钩,该事件可以直接使用。

重构器将在没有参数的情况下被调用。实例的标量(非集合)数据库映射属性将在函数内可用。急切加载的集合通常尚不可用,并且通常只包含第一个元素。在这个阶段对对象进行的 ORM 状态更改不会被记录到下一个 flush()操作中,因此重构器内的活动应该保守。

另请参阅

InstanceEvents.load()

代码语言:javascript复制
class sqlalchemy.orm.Mapper

定义了 Python 类与数据库表或其他关系结构之间的关联,以便对该类进行 ORM 操作。

Mapper对象是使用registry对象上存在的映射方法实例化的。有关实例化新Mapper对象的信息,请参阅 ORM 映射类概述。

成员

init(), add_properties(), add_property(), all_orm_descriptors, attrs, base_mapper, c, cascade_iterator(), class_, class_manager, column_attrs, columns, common_parent(), composites, concrete, configured, entity, get_property(), get_property_by_column(), identity_key_from_instance(), identity_key_from_primary_key(), identity_key_from_row(), inherits, is_mapper, is_sibling(), isa(), iterate_properties, local_table, mapped_table, mapper, non_primary, persist_selectable, polymorphic_identity, polymorphic_iterator(), polymorphic_map, polymorphic_on, primary_key, primary_key_from_instance(), primary_mapper(), relationships, selectable, self_and_descendants, single, synonyms, tables, validators, with_polymorphic_mappers

类签名

sqlalchemy.orm.Mapper (sqlalchemy.orm.ORMFromClauseRolesqlalchemy.orm.ORMEntityColumnsClauseRolesqlalchemy.sql.cache_key.MemoizedHasCacheKeysqlalchemy.orm.base.InspectionAttrsqlalchemy.log.Identifiedsqlalchemy.inspection.Inspectablesqlalchemy.event.registry.EventTargettyping.Generic)

代码语言:javascript复制
method __init__(class_: Type[_O], local_table: FromClause | None = None, properties: Mapping[str, MapperProperty[Any]] | None = None, primary_key: Iterable[_ORMColumnExprArgument[Any]] | None = None, non_primary: bool = False, inherits: Mapper[Any] | Type[Any] | None = None, inherit_condition: _ColumnExpressionArgument[bool] | None = None, inherit_foreign_keys: Sequence[_ORMColumnExprArgument[Any]] | None = None, always_refresh: bool = False, version_id_col: _ORMColumnExprArgument[Any] | None = None, version_id_generator: Literal[False] | Callable[[Any], Any] | None = None, polymorphic_on: _ORMColumnExprArgument[Any] | str | MapperProperty[Any] | None = None, _polymorphic_map: Dict[Any, Mapper[Any]] | None = None, polymorphic_identity: Any | None = None, concrete: bool = False, with_polymorphic: _WithPolymorphicArg | None = None, polymorphic_abstract: bool = False, polymorphic_load: Literal['selectin', 'inline'] | None = None, allow_partial_pks: bool = True, batch: bool = True, column_prefix: str | None = None, include_properties: Sequence[str] | None = None, exclude_properties: Sequence[str] | None = None, passive_updates: bool = True, passive_deletes: bool = False, confirm_deleted_rows: bool = True, eager_defaults: Literal[True, False, 'auto'] = 'auto', legacy_is_orphan: bool = False, _compiled_cache_size: int = 100)

一个新的 Mapper 对象的直接构造函数。

不直接调用 Mapper 构造函数,通常通过使用 registry 对象通过声明式或命令式映射样式调用。

在 2.0 版本中进行了更改:公开的 mapper() 函数已移除;对于传统的映射配置,请使用 registry.map_imperatively() 方法。

下面记录的参数可以传递给 registry.map_imperatively() 方法,或者可以在具有声明性的 Mapper 配置选项中描述的 __mapper_args__ 声明类属性中传递。

参数:

class_ – 要映射的类。在使用声明式时,此参数将自动传递为声明的类本身。

local_table – 要映射到的 Table 或其他 FromClause(即可选择的)。如果此映射器使用单表继承从另一个映射器继承,则可以为 None。在使用声明式时,此参数由扩展自动传递,根据通过 DeclarativeBase.__table__ 属性配置的内容或通过 DeclarativeBase.__tablename__ 属性的结果产生的 Table

polymorphic_abstract

表示此类将在多态层次结构中映射,但不会直接实例化。该类通常被映射,只是在继承层次结构中没有对 Mapper.polymorphic_identity 的要求。但是,该类必须是使用基类中的 Mapper.polymorphic_on 的多态继承方案的一部分。

2.0 版中的新功能。

另请参见

使用 polymorphic_abstract 构建更深层次的层次结构

always_refresh – 如果为 True,则为此映射类的所有查询操作将覆盖已存在于会话中的对象实例中的所有数据,用从数据库加载的任何信息擦除任何内存中的更改。强烈不建议使用此标志;作为替代方案,请参见方法 Query.populate_existing()

allow_partial_pks – 默认为 True。表示具有一些 NULL 值的复合主键应被视为可能存在于数据库中。这会影响映射器是否将传入的行分配给现有标识,以及 Session.merge() 是否首先检查数据库中特定主键值。例如,如果已映射到 OUTER JOIN,则可能会出现“部分主键”。

batch – 默认为 True,表示可以将多个实体的保存操作一起批处理以提高效率。将其设置为 False 表示在保存下一个实例之前将完全保存一个实例。这在极为罕见的情况下使用,即 MapperEvents 监听器需要在单个行持久性操作之间被调用的情况下。

column_prefix

一个字符串,当将 Column 对象自动分配为映射类的属性时,将会在映射属性名称之前添加。不影响在 Mapper.properties 字典中显式映射的 Column 对象。

此参数通常与将 Table 对象保持分开的命令式映射一起使用。假设 user_table Table 对象具有名为 user_iduser_namepassword 的列:

代码语言:javascript复制
class User(Base):
    __table__ = user_table
    __mapper_args__ = {'column_prefix':'_'}

上述映射将 user_iduser_namepassword 列分配给映射的 User 类上名为 _user_id_user_name_password 的属性。

Mapper.column_prefix 参数在现代用法中不常见。对于处理反射表,更灵活的自动命名方案是拦截反射时的 Column 对象;请参阅从反射表自动化列命名方案一节中关于此用法模式的注释。

concrete

如果为 True,则表示此映射器应使用具体表继承与其父映射器。

请参阅具体表继承中的示例。

confirm_deleted_rows – 默认为 True;当基于特定主键发生 DELETE 时,如果匹配的行数不等于预期的行数,则会发出警告。可以将此参数设置为 False,以处理数据库 ON DELETE CASCADE 规则可能自动删除某些行的情况。警告可能在将来的版本中更改为异常。

eager_defaults

如果为 True,则 ORM 将在 INSERT 或 UPDATE 后立即获取服务器生成的默认值的值,而不是将其保留为过期以在下次访问时获取。这可以用于需要在 flush 完成之前立即获取服务器生成值的事件方案。

值的获取可以通过在 INSERTUPDATE 语句中与 RETURNING 一起使用,或者在 INSERTUPDATE 之后添加额外的 SELECT 语句,如果后端不支持 RETURNING

使用 RETURNING 对于 SQLAlchemy 可以利用 insertmanyvalues 特别适用于 INSERT 语句,而使用额外的 SELECT 相对性能较差,增加了额外的 SQL 往返,如果这些新属性不被访问,则这些往返是不必要的。

因此,Mapper.eager_defaults 默认为字符串值"auto",表示应该使用 RETURNING 获取 INSERT 的服务器默认值,如果后端数据库支持的话,并且如果正在使用的方言支持“insertmanyreturning”作为 INSERT 语句。如果后端数据库不支持 RETURNING 或者“insertmanyreturning”不可用,则不会获取服务器默认值。

从版本 2.0.0rc1 开始更改:为 Mapper.eager_defaults 添加了“auto”选项

另请参阅

获取服务器生成的默认值

从版本 2.0.0 开始更改:RETURNING现在可以同时使用插入多行的 insertmanyvalues 功能,这使得支持的后端上的Mapper.eager_defaults特性性能非常高。

exclude_properties

排除映射的字符串列名列表或集合。

另请参见

映射表列的子集

include_properties

要映射的字符串列名的包含列表或集合。

另请参见

映射表列的子集

inherits

映射类或其中一个的对应Mapper,指示此Mapper应从中继承的超类。此处映射的类必须是另一个映射器类的子类。在使用声明式时,此参数会自动传递,因为已声明类的自然类层次结构。

另请参见

映射类继承层次结构

inherit_condition – 对于联接表继承,定义两个表如何连接的 SQL 表达式;默认为两个表之间的自然连接。

inherit_foreign_keys – 当使用inherit_condition并且存在的列缺少ForeignKey配置时,可以使用此参数来指定哪些列是“外键”。在大多数情况下可以保持为None

legacy_is_orphan

布尔值,默认为False。当为True时,指定对由此映射器映射的对象应用“传统”孤立考虑,这意味着仅当它从指向此映射器的所有父级中解除关联时,即将删除孤立级联的挂起(即,非持久性)对象才会自动从所拥有的Session中清除。新的默认行为是,当对象与指定了delete-orphan级联的任何父级之一解除关联时,对象会自动从其父级中清除。此行为与持久性对象的行为更一致,并允许行为在更多的场景中独立于孤立对象是否已刷新。

有关此更改的详细信息和示例,请参见将“待处理”对象视为“孤立”对象的考虑更为积极。

non_primary

指定此Mapper

除了“主”映射器之外,也就是用于持久化的映射器。在此创建的Mapper可用于将类的临时映射到备用可选择的对象上,仅用于加载。

自版本 1.3 起已弃用:mapper.non_primary参数已弃用,并将在将来的发布版本中删除。非主映射器的功能现在更适合使用AliasedClass构造,1.3 中也可以作为relationship()的目标使用。

另请参阅

与别名类的关系 - 新模式,消除了Mapper.non_primary标志的需要。

passive_deletes -

指示在删除联合表继承实体时外键列的 DELETE 行为。基本映射器默认为False;对于继承映射器,默认为False,除非在超类映射器上将值设置为True

当为True时,假定已在将此映射器的表与其超类表链接的外键关系上配置了 ON DELETE CASCADE,以便当工作单元尝试删除实体时,只需为超类表发出 DELETE 语句,而不是为此表发出 DELETE 语句。

当为False时,将为此映射器的表分别发出 DELETE 语句。如果此表的本地主键属性未加载,则必须发出 SELECT 以验证这些属性;请注意,联合表子类的主键列不是对象整体的“主键”部分。

请注意,True的值始终强制应用于子类映射器;也就是说,超类无法指定无主动删除而不对所有子类映射器产生影响。

另请参阅

在 ORM 关系中使用外键 ON DELETE 级联 - 描述了与relationship()一起使用的类似功能。

mapper.passive_updates - 支持联合表继承映射的 ON UPDATE CASCADE

passive_updates -

指示联合表继承映射中主键列更改时外键列的 UPDATE 行为。默认为True

当为 True 时,假定数据库上的外键已配置为 ON UPDATE CASCADE,并且数据库将处理从源列到联合表行上的依赖列的 UPDATE 传播。

当为 False 时,假定数据库不执行参照完整性,并且不会为更新发出自己的 CASCADE 操作。在主键更改期间,工作单元过程将针对依赖列发出 UPDATE 语句。

另请参阅

可变主键 / 更新级联 - 描述与 relationship() 一起使用的类似功能的说明

mapper.passive_deletes - 为连接表继承映射器支持 ON DELETE CASCADE

polymorphic_load

在继承层次结构中的子类中指定“多态加载”行为(仅适用于连接和单表继承)。有效值为:

  • “‘inline’” - 指定此类应该是“with_polymorphic”映射器的一部分,例如,它的列将包含在针对基础的 SELECT 查询中。
  • “‘selectin’” - 指定当加载此类的实例时,将发出额外的 SELECT 来检索特定于此子类的列。SELECT 使用 IN 一次性检索多个子类。

版本 1.2 中的新功能。

另请参阅

在映射器上配置 with_polymorphic()

使用 selectin_polymorphic()

polymorphic_on

指定用于确定传入行的目标类的列、属性或 SQL 表达式,当存在继承类时。

可以指定为字符串属性名称,也可以指定为 SQL 表达式,例如 Column 或在声明性映射中为 mapped_column() 对象。通常期望 SQL 表达式对应于基础映射的最底层映射的 Table 中的列:

代码语言:javascript复制
class Employee(Base):
    __tablename__ = 'employee'

    id: Mapped[int] = mapped_column(primary_key=True)
    discriminator: Mapped[str] = mapped_column(String(50))

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

它也可以指定为 SQL 表达式,如此示例中我们使用 case() 构造来提供条件方法:

代码语言:javascript复制
class Employee(Base):
    __tablename__ = 'employee'

    id: Mapped[int] = mapped_column(primary_key=True)
    discriminator: Mapped[str] = mapped_column(String(50))

    __mapper_args__ = {
        "polymorphic_on":case(
            (discriminator == "EN", "engineer"),
            (discriminator == "MA", "manager"),
            else_="employee"),
        "polymorphic_identity":"employee"
    }

它也可能使用其字符串名称引用任何属性,在使用注释列配置时特别有用:

代码语言:javascript复制
class Employee(Base):
    __tablename__ = 'employee'

    id: Mapped[int] = mapped_column(primary_key=True)
    discriminator: Mapped[str]

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

当将 polymorphic_on 设置为引用不存在于本地映射的 Table 中的属性或表达式时,但是鉴别器的值应该持久化到数据库中时,鉴别器的值不会自动设置在新实例上;这必须由用户处理,可以通过手动方式或通过事件监听器来处理。建立这样一个监听器的典型方法如下所示:

代码语言:javascript复制
from sqlalchemy import event
from sqlalchemy.orm import object_mapper

@event.listens_for(Employee, "init", propagate=True)
def set_identity(instance, *arg, **kw):
    mapper = object_mapper(instance)
    instance.discriminator = mapper.polymorphic_identity

在上述情况下,我们将映射类的polymorphic_identity值分配给discriminator属性,从而将该值持久化到数据库中的discriminator列中。

警告

目前,只能设置一个鉴别器列,通常在层次结构中的最底层类上。尚不支持“级联”多态列。

参见

映射类继承层次结构

polymorphic_identity

指定由Mapper.polymorphic_on设置引用的列表达式返回的值,用于识别此特定类的值。当接收到行时,与Mapper.polymorphic_on列表达式对应的值将与此值进行比较,指示应使用哪个子类来重建新对象。

参见

映射类继承层次结构

properties

将对象属性的字符串名称映射到MapperProperty实例的字典,这些实例定义了该属性的持久化行为。请注意,在映射到映射TableColumn对象时,除非被覆盖,否则会自动将其放置到ColumnProperty实例中。使用声明时,此参数将根据在声明类体中声明的所有这些MapperProperty实例自动传递。

参见

属性字典 - 在 ORM 映射类概述中

primary_key

一组Column对象,或者是指向Column的属性名称的字符串名称,这些属性定义了要针对此映射器的可选择单元使用的主键。这通常只是local_table的主键,但可以在此处进行覆盖。

从版本 2.0.2 开始更改:Mapper.primary_key参数也可以表示为字符串属性名称。

参见

映射到一组显式主键列 - 背景和示例用法

version_id_col

用于保持表中行的运行版本 ID 的Column。这用于检测并发更新或刷新中存在过时数据的存在。方法是检测如果 UPDATE 语句与最后已知的版本 ID 不匹配,则抛出StaleDataError异常。默认情况下,列必须是Integer类型,除非version_id_generator指定了替代版本生成器。

另请参阅

配置版本计数器 - 版本计数和原理的讨论。

version_id_generator

定义如何生成新版本 ID。默认为None,表示采用简单的整数计数方案。要提供自定义版本计数方案,请提供一个形如以下的可调用函数:

代码语言:javascript复制
def generate_version(version):
    return next_version

或者,可以使用服务器端版本控制功能,例如触发器,或者在版本 ID 生成器之外的程序化版本控制方案,通过指定值False。请参阅服务器端版本计数器以了解在使用此选项时的重要要点的讨论。

另请参阅

自定义版本计数器/类型

服务器端版本计数器

with_polymorphic

一个形如(<classes>, <selectable>)的元组,表示“多态”加载的默认样式,即一次查询哪些表。<classes>是任何指示一次加载的继承类的单个或列表的映射器和/或类。特殊值'*'可用于指示应立即加载所有后代类。第二个元组参数<selectable>指示将用于查询多个类的可选择项。

在现代映射中,Mapper.polymorphic_load参数可能比使用Mapper.with_polymorphic更可取,以指示多态加载样式的子类技术。

另请参阅

在映射器上配置 with_polymorphic()

代码语言:javascript复制
method add_properties(dict_of_properties)

将给定的属性字典添加到此映射器中,使用add_property

代码语言:javascript复制
method add_property(key: str, prop: Column[Any] | MapperProperty[Any]) → None

向此映射器添加单个 MapperProperty。

如果尚未配置映射器,则只需将属性添加到发送到构造函数的初始属性字典中。如果此映射器已配置,则立即配置给定的 MapperProperty。

代码语言:javascript复制
attribute all_orm_descriptors

一个包含与映射类关联的所有InspectionAttr属性的命名空间。

这些属性在所有情况下都是与映射类或其超类关联的 Python 描述符。

此命名空间包括映射到类的属性以及由扩展模块声明的属性。它包括任何从InspectionAttr继承的 Python 描述符类型。这包括QueryableAttribute,以及扩展类型,如hybrid_propertyhybrid_methodAssociationProxy

为了区分映射属性和扩展属性,属性InspectionAttr.extension_type将引用一个常量,用于区分不同的扩展类型。

属性的排序基于以下规则:

  1. 从子类到超类按顺序迭代类及其超类(即通过cls.__mro__迭代)
  2. 对于每个类,按照它们在__dict__中出现的顺序生成属性,但以下步骤除外。在 Python 3.6 及以上版本中,此顺序将与类的构造相同,但有一个例外,即应用程序或映射器后来添加的属性。
  3. 如果某个属性键也在超类__dict__中,那么它将包含在该类的迭代中,而不是它首次出现的类中。

上述过程产生了一种确定性排序,该排序是根据属性被分配给类的顺序确定的。

自版本 1.3.19 更改:确保对Mapper.all_orm_descriptors()的确定性排序。

当处理QueryableAttribute时,QueryableAttribute.property属性引用了MapperProperty属性,当通过Mapper.attrs引用映射属性集合时,将得到它。

警告

Mapper.all_orm_descriptors访问器命名空间是OrderedProperties的一个实例。这是一个类似字典的对象,包括一小部分命名方法,如OrderedProperties.items()OrderedProperties.values()。当动态访问属性时,建议使用字典访问方案,例如mapper.all_orm_descriptors[somename],而不是getattr(mapper.all_orm_descriptors, somename),以避免名称冲突。

另请参阅

Mapper.attrs

代码语言:javascript复制
attribute attrs

该映射器的所有MapperProperty对象的命名空间。

这是一个根据其键名提供每个属性的对象。例如,具有User.name属性的User类的映射器将提供mapper.attrs.name,这将是代表name列的ColumnProperty。命名空间对象还可以进行迭代,这将产生每个MapperProperty

Mapper具有该属性的几个预过滤视图,限制了返回的属性类型,包括synonymscolumn_attrsrelationshipscomposites

警告

Mapper.attrs访问器命名空间是OrderedProperties的一个实例。这是一个类似字典的对象,包括一小部分命名方法,如OrderedProperties.items()OrderedProperties.values()。当动态访问属性时,建议使用字典访问方案,例如mapper.attrs[somename],而不是getattr(mapper.attrs, somename),以避免名称冲突。

另请参阅

Mapper.all_orm_descriptors

代码语言:javascript复制
attribute base_mapper: Mapper[Any]

继承链中最基础的Mapper

在非继承场景中,此属性始终为此Mapper。在继承场景中,它引用继承链中所有其他Mapper对象的父级Mapper

这是在映射器构建期间确定的只读属性。如果直接修改,行为未定义。

代码语言:javascript复制
attribute c: ReadOnlyColumnCollection[str, Column[Any]]

Mapper.columns的同义词。

代码语言:javascript复制
method cascade_iterator(type_: str, state: InstanceState[_O], halt_on: Callable[[InstanceState[Any]], bool] | None = None) → Iterator[Tuple[object, Mapper[Any], InstanceState[Any], _InstanceDict]]

遍历对象图中的每个元素及其映射器,对于符合给定级联规则的所有关系。

参数:

  • type_ – 级联规则的名称(即"save-update""delete"等)。 注意 在此处不接受"all"级联。有关通用对象遍历函数,请参阅如何遍历与给定对象相关的所有对象?。
  • state – 主要的 InstanceState。子项将根据为此对象的映射器定义的关系进行处理。

返回:

该方法产生单个对象实例。

另请参阅

级联

如何遍历与给定对象相关的所有对象? - 演示了一个通用函数,用于遍历所有对象而不依赖于级联。

代码语言:javascript复制
attribute class_: Type[_O]

Mapper映射到的类。

代码语言:javascript复制
attribute class_manager: ClassManager[_O]

ClassManager维护此Mapper的事件监听器和类绑定描述符。

这是在映射器构建期间确定的只读属性。如果直接修改,行为是未定义的。

代码语言:javascript复制
attribute column_attrs

返回此Mapper维护的所有ColumnProperty属性的命名空间。

另请参阅

Mapper.attrs - 所有MapperProperty对象的命名空间。

代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

由此Mapper维护的Column或其他标量表达式对象的集合。

该集合的行为与任何Table对象上的c属性相同,只是此映射中包含的列,且基于映射中定义的属性名称进行键控,而不一定是Column本身的key属性。此外,由column_property()映射的标量表达式也在此处。

这是在映射器构建期间确定的只读属性。如果直接修改,行为是未定义的。

代码语言:javascript复制
method common_parent(other: Mapper[Any]) → bool

如果给定的映射器与此映射器共享一个共同的继承父级,则返回 true。

代码语言:javascript复制
attribute composites

返回此Mapper维护的所有Composite属性的命名空间。

另请参阅

Mapper.attrs - 所有MapperProperty对象的命名空间。

代码语言:javascript复制
attribute concrete: bool

如果此Mapper是具体继承映射器,则表示True

这是在映射器构建期间确定的只读属性。如果直接修改,行为是未定义的。

代码语言:javascript复制
attribute configured: bool = False

如果已配置此Mapper,则表示True

这是在映射器构建期间确定的只读属性。如果直接修改,行为是未定义的。

另请参阅

configure_mappers()

代码语言:javascript复制
attribute entity

检查 API 的一部分。

返回 self.class_。

代码语言:javascript复制
method get_property(key: str, _configure_mappers: bool = False) → MapperProperty[Any]

返回与给定键关联的 MapperProperty。

代码语言:javascript复制
method get_property_by_column(column: ColumnElement[_T]) → MapperProperty[_T]

给定Column对象,返回映射到此列的MapperProperty

代码语言:javascript复制
method identity_key_from_instance(instance: _O) → _IdentityKeyType[_O]

根据其主键属性返回给定实例的标识键。

如果实例的状态已过期,则调用此方法将导致数据库检查以查看对象是否已被删除。如果行不再存在,则引发ObjectDeletedError

此值通常也在实例状态下以属性名称键的形式找到。

代码语言:javascript复制
method identity_key_from_primary_key(primary_key: Tuple[Any, ...], identity_token: Any | None = None) → _IdentityKeyType[_O]

返回一个用于在标识映射中存储/检索项目的标识映射键。

参数:

primary_key - 表示标识符的值列表。

代码语言:javascript复制
method identity_key_from_row(row: Row[Any] | RowMapping | None, identity_token: Any | None = None, adapter: ORMAdapter | None = None) → _IdentityKeyType[_O]

返回用于在标识映射中存储/检索项目的标识映射键。

参数:

-

从选择了 ORM 映射的主键列的结果集生成的RowRowMapping

从版本 2.0 开始:RowRowMapping被接受作为“row”参数

代码语言:javascript复制
attribute inherits: Mapper[Any] | None

引用此Mapper继承自的Mapper(如果有)。

代码语言:javascript复制
attribute is_mapper = True

检查 API 的一部分。

代码语言:javascript复制
method is_sibling(other: Mapper[Any]) → bool

如果另一个映射器是此映射器的继承兄弟,则返回 true。共同的父级但不同的分支

代码语言:javascript复制
method isa(other: Mapper[Any]) → bool

如果此映射器从给定的映射器继承,则返回 True。

代码语言:javascript复制
attribute iterate_properties

返回所有 MapperProperty 对象的迭代器。

代码语言:javascript复制
attribute local_table: FromClause

Mapper所引用的直接FromClause

通常是Table的一个实例,可以是任何FromClause

“本地”表是Mapper直接负责管理的可选择的表,从属性访问和 flush 的角度来看。对于非继承映射器,Mapper.local_table将与Mapper.persist_selectable相同。对于继承映射器,Mapper.local_table指的是包含该Mapper正在加载/持久化的列的特定部分,例如加入中的特定Table

另请参阅

Mapper.persist_selectable

Mapper.selectable.

代码语言:javascript复制
attribute mapped_table

自版本 1.3 起已弃用:使用 .persist_selectable

代码语言:javascript复制
attribute mapper

是检查 API 的一部分。

返回自身。

代码语言:javascript复制
attribute non_primary: bool

如果此Mapper是“非主”映射器,例如仅用于选择行而不用于持久化管理,则表示为 True

这是在映射器构造期间确定的只读属性。如果直接修改,则行为未定义。

代码语言:javascript复制
attribute persist_selectable: FromClause

Mapper映射到的FromClause

通常是Table的一个实例,可以是任何FromClause

Mapper.persist_selectable类似于Mapper.local_table,但表示继承方案中整体表示继承类层次结构的FromClause

:attr..Mapper.persist_selectable也与Mapper.selectable属性分开,后者可能是用于选择列的替代子查询。:attr..Mapper.persist_selectable针对的是在持久化操作中将被写入的列。

另请参阅

Mapper.selectable

Mapper.local_table

代码语言:javascript复制
attribute polymorphic_identity: Any | None

表示一个标识符,该标识符在结果行加载期间与Mapper.polymorphic_on列匹配。

仅在继承时使用,此对象可以是与由Mapper.polymorphic_on表示的列的类型可比较的任何类型。

这是在映射器构造期间确定的只读属性。如果直接修改,则行为未定义。

代码语言:javascript复制
method polymorphic_iterator() → Iterator[Mapper[Any]]

遍历包括此映射器和所有后代映射器在内的集合。

这不仅包括直接继承的映射器,还包括所有它们的继承映射器。

要遍历整个层次结构,请使用mapper.base_mapper.polymorphic_iterator()

代码语言:javascript复制
attribute polymorphic_map: Dict[Any, Mapper[Any]]

在继承场景中,将“多态身份”标识符映射到Mapper实例。

标识符可以是与Mapper.polymorphic_on所表示的列的类型可比较的任何类型。

映射器的继承链都将引用相同的多态映射对象。该对象用于将传入的结果行与目标映射器相关联。

这是在映射器构造期间确定的只读属性。如果直接修改,则行为未定义。

代码语言:javascript复制
attribute polymorphic_on: KeyedColumnElement[Any] | None

Mapperpolymorphic_on参数指定的Column或 SQL 表达式,在继承场景中。

此属性通常是一个Column实例,但也可能是一个表达式,例如从cast()派生的表达式。

这是在映射器构造期间确定的只读属性。如果直接修改,则行为未定义。

代码语言:javascript复制
attribute primary_key: Tuple[Column[Any], ...]

包含作为此Mapper在表映射的‘主键’的一部分的Column对象的集合的可迭代对象,从此Mapper的角度来看。

这个列表与Mapper.persist_selectable中的可选择项相对。在继承映射器的情况下,一些列可能由超类映射器管理。例如,在Join的情况下,主键由Join引用的所有表的主键列确定。

此列表也不一定与与基础表关联的主键列集合相同;Mapper具有可以覆盖Mapper认为是主键列的primary_key参数。

这是一个只读属性,在映射器构造期间确定。如果直接修改,行为是未定义的。

代码语言:javascript复制
method primary_key_from_instance(instance: _O) → Tuple[Any, ...]

返回给定实例的主键值列表。

如果实例的状态已过期,则调用此方法将导致数据库检查以查看对象是否已被删除。如果行不再存在,则会引发ObjectDeletedError

代码语言:javascript复制
method primary_mapper() → Mapper[Any]

返回与此映射器的类键(类)对应的主映射器。

代码语言:javascript复制
attribute relationships

由此Mapper维护的所有Relationship属性的命名空间。

警告

Mapper.relationships 访问器命名空间是OrderedProperties的实例。这是一个类似于字典的对象,其中包含少量命名方法,例如OrderedProperties.items()OrderedProperties.values()。在动态访问属性时,应优先使用字典访问方案,例如mapper.relationships[somename]而不是getattr(mapper.relationships, somename),以避免名称冲突。

另请参阅

Mapper.attrs - 所有MapperProperty对象的命名空间。

代码语言:javascript复制
attribute selectable

默认情况下,此Mapper从中选择的FromClause构造。

通常情况下,这等同于persist_selectable,除非使用了with_polymorphic功能,在这种情况下,将返回完整的“多态”可选择项。

代码语言:javascript复制
attribute self_and_descendants

包括此映射器和所有后代映射器的集合。

这不仅包括直接继承的映射器,还包括所有它们继承的映射器。

代码语言:javascript复制
attribute single: bool

如果此 Mapper 是单表继承映射器,则表示 True

如果设置了此标志,Mapper.local_table 将为 None

这是在映射器构建期间确定的只读属性。如果直接修改,行为未定义。

代码语言:javascript复制
attribute synonyms

返回此 Mapper 维护的所有 Synonym 属性的命名空间。

另请参阅

Mapper.attrs - 所有 MapperProperty 对象的命名空间。

代码语言:javascript复制
attribute tables: Sequence[TableClause]

包含此 Mapper 意识到的所有 TableTableClause 对象的序列。

如果映射器被映射到一个 Join 或者代表 SelectAlias,构成完整结构的各个 Table 对象将在这里表示。

这是在映射器构建期间确定的只读属性。如果直接修改,行为未定义。

代码语言:javascript复制
attribute validators: util.immutabledict[str, Tuple[str, Dict[str, Any]]]

一个不可变字典,其中属性已使用 validates() 装饰器装饰。

字典包含字符串属性名称作为键,映射到实际验证方法。

代码语言:javascript复制
attribute with_polymorphic_mappers

默认“多态”查询中包含的 Mapper 对象列表。

代码语言:javascript复制
class sqlalchemy.orm.MappedAsDataclass

混合类用于指示映射此类时,还将其转换为数据类。

另请参阅

声明性数据类映射 - 完整的 SQLAlchemy 本地数据类映射背景

版本 2.0 中的新功能。

代码语言:javascript复制
class sqlalchemy.orm.MappedClassProtocol

表示 SQLAlchemy 映射类的协议。

协议对类的类型是通用的,使用 MappedClassProtocol[Any] 来允许任何映射类。

类签名

sqlalchemy.orm.MappedClassProtocol (typing_extensions.Protocol)

0 人点赞