SQLAlchemy 2.0 文档
SQLAlchemy ORM
- ORM 快速入门
- ORM 映射类配置
- 关系配置
- ORM 查询指南
- 使用 Session
- 事件和内部机制
- ORM 扩展
- ORM 示例
项目版本
ORM API 查询功能¶
ORM 加载器选项¶
加载器选项是一些对象,当传递给 Select.options()
方法(Select
对象或类似的 SQL 构造)时,会影响列和面向关系的属性的加载。 大多数加载器选项都派生自 Load
层次结构。 有关使用加载器选项的完整概述,请参阅以下链接部分。
另请参阅
列加载选项 - 详细说明影响如何加载列和 SQL 表达式映射属性的映射器和加载选项
关系加载技术 - 详细说明影响如何加载
relationship()
映射属性的关系和加载选项
ORM 执行选项¶
ORM 级别的执行选项是可以使用 Session.execute.execution_options
参数(Session
方法(如 Session.execute()
和 Session.scalars()
)接受的字典参数)与语句执行关联的关键字选项,或者通过使用 Executable.execution_options()
方法将它们直接与要调用的语句关联,该方法接受它们作为任意关键字参数。
ORM 级别选项与 Connection.execution_options()
中记录的核心级别执行选项不同。 重要的是要注意,下面讨论的 ORM 选项与核心级别方法 Connection.execution_options()
或 Engine.execution_options()
不 兼容;即使 Engine
或 Connection
与正在使用的 Session
关联,这些选项也会在此级别被忽略。
在本节中,将使用 Executable.execution_options()
方法样式进行示例说明。
填充现有对象¶
populate_existing
执行选项确保对于加载的所有行,Session
中的相应实例将被完全刷新 - 擦除对象中的任何现有数据(包括待处理的更改),并替换为从结果加载的数据。
示例用法如下所示
>>> stmt = select(User).execution_options(populate_existing=True)
>>> result = session.execute(stmt)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
...
通常,ORM 对象仅加载一次,如果它们与后续结果行中的主键匹配,则该行不会应用于该对象。 这既是为了保留对象上待处理的、未刷新的更改,也是为了避免刷新已存在的数据的开销和复杂性。 Session
假定高度隔离事务的默认工作模型,并且在期望数据在事务内本地更改之外发生更改的程度上,这些用例将使用显式步骤(如本方法)来处理。
使用 populate_existing
,可以刷新与查询匹配的任何对象集,并且还可以控制关系加载器选项。 例如,要在刷新实例的同时刷新一组相关的对象
stmt = (
select(User)
.where(User.name.in_(names))
.execution_options(populate_existing=True)
.options(selectinload(User.addresses))
)
# will refresh all matching User objects as well as the related
# Address objects
users = session.execute(stmt).scalars().all()
populate_existing
的另一个用例是支持各种属性加载功能,这些功能可以更改每个查询的属性加载方式。 应用此选项的选项包括
可以修改加载器策略加载内容的
PropComparator.and_()
方法选择要刷新哪些属性的
load_only()
选项
populate_existing
执行选项等效于 Query.populate_existing()
方法,在 1.x 风格 ORM 查询中。
自动刷新¶
当此选项作为 False
传递时,将导致 Session
不调用“自动刷新”步骤。 它等效于使用 Session.no_autoflush
上下文管理器来禁用自动刷新
>>> stmt = select(User).execution_options(autoflush=False)
>>> session.execute(stmt)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
...
此选项也适用于启用 ORM 的 Update
和 Delete
查询。
autoflush
执行选项等效于 Query.autoflush()
方法,在 1.x 风格 ORM 查询中。
另请参阅
使用 Yield Per 获取大型结果集¶
yield_per
执行选项是一个整数值,它将导致 Result
一次仅缓冲有限数量的行和/或 ORM 对象,然后再将数据提供给客户端。
通常,ORM 会立即获取所有行,为每个行构造 ORM 对象,并将这些对象组装到单个缓冲区中,然后再将此缓冲区作为要返回的行源传递给 Result
对象。 此行为的基本原理是允许连接急切加载、结果唯一化以及结果处理逻辑的一般情况(依赖于身份映射维护结果集中每个对象在获取时的状态一致性)等功能的正确行为。
yield_per
选项的目的是更改此行为,以便针对迭代非常大的结果集(例如 > 10K 行)优化 ORM 结果集,在这种情况下,用户已确定上述模式不适用。 当使用 yield_per
时,ORM 将改为将 ORM 结果批处理到子集合中,并在迭代 Result
对象时从每个子集合单独生成行,以便 Python 解释器无需声明非常大的内存区域,这既耗时又导致过多的内存使用。 此选项会影响数据库游标的使用方式,以及 ORM 如何构造要传递给 Result
的行和对象。
提示
从上面可以看出,Result
必须以可迭代的方式使用,即使用迭代(如 for row in result
)或使用部分行方法(如 Result.fetchmany()
或 Result.partitions()
)。 调用 Result.all()
将会破坏使用 yield_per
的目的。
使用 yield_per
等效于同时使用 Connection.execution_options.stream_results
执行选项(如果后端支持,则选择使用服务器端游标)和返回的 Result
对象上的 Result.yield_per()
方法,该方法建立要获取的行的固定大小以及将一次构造的 ORM 对象的相应限制。
提示
yield_per
现在也作为核心执行选项提供,在 使用服务器端游标(又名流式结果) 中详细描述。 本节详细介绍了 yield_per
作为 ORM Session
的执行选项的用法。 该选项在这两种上下文中表现得尽可能相似。
与 ORM 一起使用时,yield_per
必须通过给定语句上的 Executable.execution_options()
方法或通过将其传递给 Session.execute.execution_options
参数(Session.execute()
或其他类似的 Session
方法(如 Session.scalars()
))来建立。 以下说明了获取 ORM 对象的典型用法
>>> stmt = select(User).execution_options(yield_per=10)
>>> for user_obj in session.scalars(stmt):
... print(user_obj)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
[...] ()
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')
...
>>> # ... rows continue ...
上面的代码等效于下面的示例,该示例结合使用了 Connection.execution_options.stream_results
和 Connection.execution_options.max_row_buffer
核心级执行选项以及 Result.yield_per()
方法(Result
的方法)
# equivalent code
>>> stmt = select(User).execution_options(stream_results=True, max_row_buffer=10)
>>> for user_obj in session.scalars(stmt).yield_per(10):
... print(user_obj)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
[...] ()
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')
...
>>> # ... rows continue ...
yield_per
也常与 Result.partitions()
方法结合使用,该方法将按分组分区迭代行。 每个分区的大小默认为传递给 yield_per
的整数值,如下例所示
>>> stmt = select(User).execution_options(yield_per=10)
>>> for partition in session.scalars(stmt).partitions():
... for user_obj in partition:
... print(user_obj)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
[...] ()
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')
...
>>> # ... rows continue ...
yield_per
执行选项与使用集合时的 “子查询”急切加载 加载或 “连接”急切加载 不兼容。 它可能与 “select in”急切加载 兼容,前提是数据库驱动程序支持多个独立的游标。
此外,yield_per
执行选项与 Result.unique()
方法不兼容;由于此方法依赖于存储所有行的完整身份集,因此必然会破坏使用 yield_per
的目的,即处理任意数量的行。
在版本 1.4.6 中更改: 当从 Result
对象中提取 ORM 行时,如果该对象同时使用了 Result.unique()
过滤器和 yield_per
执行选项,则会引发异常。
当在 1.x 风格 ORM 用法中使用旧版 Query
对象时,Query.yield_per()
方法将具有与 yield_per
执行选项相同的结果。
另请参阅
身份令牌¶
“身份令牌”是可以在新加载对象的 身份键 中关联的任意值。 此元素的存在首先是为了支持执行按行“分片”的扩展,其中对象可以从任意数量的特定数据库表副本中加载,这些副本仍然具有重叠的主键值。 “身份令牌”的主要使用者是 水平分片 扩展,它为在特定数据库表的多个“分片”之间持久化对象提供了一个通用框架。
identity_token
执行选项可以基于每个查询使用,以直接影响此令牌。 直接使用它,可以在 Session
中填充具有相同主键和源表但不同“身份”的对象的多个实例。
一个这样的示例是在 Session
中填充来自不同模式中同名表的对象,使用 模式名称转换 功能,该功能可以影响查询范围内的模式选择。 给定如下映射
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
class Base(DeclarativeBase):
pass
class MyTable(Base):
__tablename__ = "my_table"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
上面类的默认“schema”名称是 None
,这意味着不会将模式限定写入 SQL 语句。 但是,如果我们使用 Connection.execution_options.schema_translate_map
,将 None
映射到备用模式,我们可以将 MyTable
的实例放置到两个不同的模式中
engine = create_engine(
"postgresql+psycopg://scott:tiger@localhost/test",
)
with Session(
engine.execution_options(schema_translate_map={None: "test_schema"})
) as sess:
sess.add(MyTable(name="this is schema one"))
sess.commit()
with Session(
engine.execution_options(schema_translate_map={None: "test_schema_2"})
) as sess:
sess.add(MyTable(name="this is schema two"))
sess.commit()
上面的两个代码块每次都创建一个链接到不同模式转换映射的 Session
对象,并且 MyTable
的实例被持久化到 test_schema.my_table
和 test_schema_2.my_table
中。
上面的 Session
对象是独立的。 如果我们想在一个事务中持久化这两个对象,我们需要使用 水平分片 扩展来执行此操作。
但是,我们可以演示在一个会话中查询这些对象,如下所示
with Session(engine) as sess:
obj1 = sess.scalar(
select(MyTable)
.where(MyTable.id == 1)
.execution_options(
schema_translate_map={None: "test_schema"},
identity_token="test_schema",
)
)
obj2 = sess.scalar(
select(MyTable)
.where(MyTable.id == 1)
.execution_options(
schema_translate_map={None: "test_schema_2"},
identity_token="test_schema_2",
)
)
obj1
和 obj2
彼此不同。 但是,它们都引用 MyTable
类的 primary key id 1,但它们是不同的。 这就是 identity_token
的作用,我们可以在检查每个对象时看到,我们在其中查看 InstanceState.key
以查看两个不同的身份令牌
>>> from sqlalchemy import inspect
>>> inspect(obj1).key
(<class '__main__.MyTable'>, (1,), 'test_schema')
>>> inspect(obj2).key
(<class '__main__.MyTable'>, (1,), 'test_schema_2')
当使用 水平分片 扩展时,上述逻辑会自动发生。
在版本 2.0.0rc1 中新增: - 添加了 identity_token
ORM 级别执行选项。
从启用 ORM 的 SELECT 和 DML 语句中检查实体和列¶
select()
构造,以及 insert()
、update()
和 delete()
构造(对于后者的 DML 构造,从 SQLAlchemy 1.4.33 开始),都支持检查在其中创建这些语句的实体,以及结果集中将返回的列和数据类型的能力。
对于 Select
对象,此信息可从 Select.column_descriptions
属性获得。 此属性的操作方式与旧版 Query.column_descriptions
属性相同。 返回的格式是字典列表
>>> from pprint import pprint
>>> user_alias = aliased(User, name="user2")
>>> stmt = select(User, User.id, user_alias)
>>> pprint(stmt.column_descriptions)
[{'aliased': False,
'entity': <class 'User'>,
'expr': <class 'User'>,
'name': 'User',
'type': <class 'User'>},
{'aliased': False,
'entity': <class 'User'>,
'expr': <....InstrumentedAttribute object at ...>,
'name': 'id',
'type': Integer()},
{'aliased': True,
'entity': <AliasedClass ...; User>,
'expr': <AliasedClass ...; User>,
'name': 'user2',
'type': <class 'User'>}]
当 Select.column_descriptions
与非 ORM 对象(例如纯 Table
或 Column
对象)一起使用时,条目将包含有关所有情况下返回的单个列的基本信息
>>> stmt = select(user_table, address_table.c.id)
>>> pprint(stmt.column_descriptions)
[{'expr': Column('id', Integer(), table=<user_account>, primary_key=True, nullable=False),
'name': 'id',
'type': Integer()},
{'expr': Column('name', String(), table=<user_account>, nullable=False),
'name': 'name',
'type': String()},
{'expr': Column('fullname', String(), table=<user_account>),
'name': 'fullname',
'type': String()},
{'expr': Column('id', Integer(), table=<address>, primary_key=True, nullable=False),
'name': 'id_1',
'type': Integer()}]
在版本 1.4.33 中变更:当 Select.column_descriptions
属性用于非 ORM 启用的 Select
时,现在会返回值。 以前,这将引发 NotImplementedError
。
对于 insert()
、update()
和 delete()
构造,有两个单独的属性。 一个是 UpdateBase.entity_description
,它返回有关 DML 构造将影响的主要 ORM 实体和数据库表的信息
>>> from sqlalchemy import update
>>> stmt = update(User).values(name="somename").returning(User.id)
>>> pprint(stmt.entity_description)
{'entity': <class 'User'>,
'expr': <class 'User'>,
'name': 'User',
'table': Table('user_account', ...),
'type': <class 'User'>}
提示
UpdateBase.entity_description
包括一个条目 "table"
,它实际上是语句要插入、更新或删除的表,这不总是与类可能映射到的 SQL “selectable” 相同。 例如,在连接表继承场景中,"table"
将引用给定实体的本地表。
另一个是 UpdateBase.returning_column_descriptions
,它以与 Select.column_descriptions
大致相似的方式提供有关 RETURNING 集合中列的信息
>>> pprint(stmt.returning_column_descriptions)
[{'aliased': False,
'entity': <class 'User'>,
'expr': <sqlalchemy.orm.attributes.InstrumentedAttribute ...>,
'name': 'id',
'type': Integer()}]
在版本 1.4.33 中新增:添加了 UpdateBase.entity_description
和 UpdateBase.returning_column_descriptions
属性。
其他 ORM API 构造¶
对象名称 | 描述 |
---|---|
aliased(element[, alias, name, flat, ...]) |
生成给定元素的别名,通常是 |
表示映射类的“别名”形式,用于 Query。 |
|
为 |
|
由 |
|
join(left, right[, onclause, isouter, ...]) |
在 left 和 right 子句之间生成内连接。 |
outerjoin(left, right[, onclause, full]) |
在 left 和 right 子句之间生成左外连接。 |
with_loader_criteria(entity_or_base, where_criteria[, loader_only, include_aliases, ...]) |
为特定实体的所有出现次数的加载添加额外的 WHERE 条件。 |
with_parent(instance, prop[, from_entity]) |
创建过滤条件,使用已建立的 |
- function sqlalchemy.orm.aliased(element: _EntityType[_O] | FromClause, alias: FromClause | None = None, name: str | None = None, flat: bool = False, adapt_on_names: bool = False) → AliasedClass[_O] | FromClause | AliasedType[_O]¶
生成给定元素的别名,通常是
AliasedClass
实例。例如:
my_alias = aliased(MyClass) stmt = select(MyClass, my_alias).filter(MyClass.id > my_alias.id) result = session.execute(stmt)
aliased()
函数用于创建映射类到新 selectable 的临时映射。 默认情况下,selectable 是从通常映射的 selectable(通常是Table
)使用FromClause.alias()
方法生成的。 但是,aliased()
也可用于将类链接到新的select()
语句。 此外,with_polymorphic()
函数是aliased()
的变体,旨在指定所谓的“多态 selectable”,它对应于多个连接继承子类的联合。为了方便起见,
aliased()
函数还接受纯FromClause
构造,例如Table
或select()
构造。 在这些情况下,FromClause.alias()
方法在对象上被调用,并返回新的Alias
对象。 在这种情况下,返回的Alias
未进行 ORM 映射。- 参数:
element¶ – 要别名的元素。 通常是映射类,但为了方便起见,也可以是
FromClause
元素。alias¶ – 可选的 selectable 单元,用于将元素映射到该单元。 这通常用于将对象链接到子查询,并且应该是别名化的 select 构造,就像从
Query.subquery()
方法或Select.subquery()
或Select.alias()
方法生成的select()
构造一样。name¶ – 可选的字符串名称,用于别名,如果未由
alias
参数指定。 该名称,除其他外,构成将通过Query
对象返回的元组访问的属性名称。 当创建Join
对象的别名时,不支持此参数。flat¶ –
布尔值,将传递给
FromClause.alias()
调用,以便Join
对象的别名将别名化连接内部的各个表,而不是创建子查询。 这通常被所有现代数据库支持,关于右嵌套连接,并且通常产生更高效的查询。当
aliased.flat
与aliased.name
结合使用时,生成的连接将使用类似于<prefix>_<tablename>
的命名方案来别名化各个表。 此命名方案仅用于可见性/调试目的,具体方案如有更改,恕不另行通知。在版本 2.0.32 中新增:添加了对结合
aliased.name
和aliased.flat
的支持。 以前,这将引发NotImplementedError
。adapt_on_names¶ –
如果为 True,则当将 ORM 实体的映射列映射到给定 selectable 的列时,将使用更宽松的“匹配” - 如果给定的 selectable 没有与实体上的列对应的列,则将执行基于名称的匹配。 这种情况的用例是将实体与某些派生的 selectable 关联,例如使用聚合函数的 selectable
class UnitPrice(Base): __tablename__ = "unit_price" ... unit_id = Column(Integer) price = Column(Numeric) aggregated_unit_price = ( Session.query(func.sum(UnitPrice.price).label("price")) .group_by(UnitPrice.unit_id) .subquery() ) aggregated_unit_price = aliased( UnitPrice, alias=aggregated_unit_price, adapt_on_names=True )
在上面,引用
aggregated_unit_price
上.price
的函数将返回func.sum(UnitPrice.price).label('price')
列,因为它与名称“price”匹配。 通常,“price”函数与实际的UnitPrice.price
列没有任何“列对应关系”,因为它不是原始列的代理。
- class sqlalchemy.orm.util.AliasedClass¶
表示映射类的“别名”形式,用于 Query。
ORM 等效于
alias()
构造,此对象使用__getattr__
方案模仿映射类,并维护对真实Alias
对象的引用。AliasedClass
的主要目的是充当 ORM 生成的 SQL 语句中的替代项,以便现有的映射实体可以在多个上下文中使用。 一个简单的例子# find all pairs of users with the same name user_alias = aliased(User) session.query(User, user_alias).join( (user_alias, User.id > user_alias.id) ).filter(User.name == user_alias.name)
AliasedClass
也能够将现有的映射类映射到全新的 selectable,前提是此 selectable 与现有的映射 selectable 在列方面兼容,并且它可以在映射中配置为relationship()
的目标。 请参阅下面的链接以获取示例。AliasedClass
对象通常使用aliased()
函数构造。 当使用with_polymorphic()
函数时,它也会通过额外的配置生成。结果对象是
AliasedClass
的实例。 此对象实现了一种属性方案,该方案生成与原始映射类相同的属性和方法接口,允许AliasedClass
与任何适用于原始类的属性技术兼容,包括混合属性(请参阅 混合属性)。可以使用
inspect()
检查AliasedClass
的底层Mapper
、别名化的 selectable 和其他信息from sqlalchemy import inspect my_alias = aliased(MyClass) insp = inspect(my_alias)
结果检查对象是
AliasedInsp
的实例。类签名
class
sqlalchemy.orm.AliasedClass
(sqlalchemy.inspection.Inspectable
,sqlalchemy.orm.ORMColumnsClauseRole
)
- class sqlalchemy.orm.util.AliasedInsp¶
为
AliasedClass
对象提供检查接口。AliasedInsp
对象是使用inspect()
函数为AliasedClass
返回的from sqlalchemy import inspect from sqlalchemy.orm import aliased my_alias = aliased(MyMappedClass) insp = inspect(my_alias)
AliasedInsp
上的属性包括entity
- 表示的AliasedClass
。mapper
- 映射底层类的Mapper
。name
- 别名的名称。 也用作从Query
返回的结果元组中的属性名称。with_polymorphic_mappers
-Mapper
对象的集合,指示AliasedClass
的 select 构造中表达的所有 mapper。polymorphic_on
- 备用列或 SQL 表达式,将用作多态加载的“鉴别器”。
另请参阅
类签名
class
sqlalchemy.orm.AliasedInsp
(sqlalchemy.orm.ORMEntityColumnsClauseRole
,sqlalchemy.orm.ORMFromClauseRole
,sqlalchemy.sql.cache_key.HasCacheKey
,sqlalchemy.orm.base.InspectionAttr
,sqlalchemy.util.langhelpers.MemoizedSlots
,sqlalchemy.inspection.Inspectable
,typing.Generic
)
- class sqlalchemy.orm.Bundle¶
由
Query
在一个命名空间下返回的 SQL 表达式分组。Bundle
本质上允许嵌套由面向列的Query
对象返回的基于元组的结果。 它也可以通过简单的子类化进行扩展,其中主要的覆盖能力是如何返回表达式集,允许后处理以及自定义返回类型,而无需涉及 ORM 标识映射类。另请参阅
成员
__init__(), c, columns, create_row_processor(), is_aliased_class, is_bundle, is_clause_element, is_mapper, label(), single_entity
类签名
class
sqlalchemy.orm.Bundle
(sqlalchemy.orm.ORMColumnsClauseRole
,sqlalchemy.sql.annotation.SupportsCloneAnnotations
,sqlalchemy.sql.cache_key.MemoizedHasCacheKey
,sqlalchemy.inspection.Inspectable
,sqlalchemy.orm.base.InspectionAttr
)-
method
sqlalchemy.orm.Bundle.
__init__(name: str, *exprs: _ColumnExpressionArgument[Any], **kw: Any)¶ 构造一个新的
Bundle
。例如:
bn = Bundle("mybundle", MyClass.x, MyClass.y) for row in session.query(bn).filter(bn.c.x == 5).filter(bn.c.y == 4): print(row.mybundle.x, row.mybundle.y)
-
attribute
sqlalchemy.orm.Bundle.
c: ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]¶ Bundle.columns
的别名。
-
attribute
sqlalchemy.orm.Bundle.
columns: ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]¶ 此
Bundle
引用的 SQL 表达式的命名空间。例如:
bn = Bundle("mybundle", MyClass.x, MyClass.y) q = sess.query(bn).filter(bn.c.x == 5)
也支持 Bundle 的嵌套
b1 = Bundle( "b1", Bundle("b2", MyClass.a, MyClass.b), Bundle("b3", MyClass.x, MyClass.y), ) q = sess.query(b1).filter(b1.c.b2.c.a == 5).filter(b1.c.b3.c.y == 9)
另请参阅
-
method
sqlalchemy.orm.Bundle.
create_row_processor(query: Select[Any], procs: Sequence[Callable[[Row[Any]], Any]], labels: Sequence[str]) → Callable[[Row[Any]], Any]¶ 为此
Bundle
生成 “行处理” 函数。子类可以重写此方法,以便在获取结果时提供自定义行为。此方法在查询执行时被传递 statement 对象和一组 “行处理器” 函数;这些处理器函数在给定结果行时将返回单个属性值,然后可以将其适配为任何类型的返回数据结构。
下面的示例说明了如何用纯 Python 字典替换通常的
Row
返回结构from sqlalchemy.orm import Bundle class DictBundle(Bundle): def create_row_processor(self, query, procs, labels): "Override create_row_processor to return values as dictionaries" def proc(row): return dict(zip(labels, (proc(row) for proc in procs))) return proc
来自上述
Bundle
的结果将返回字典值bn = DictBundle("mybundle", MyClass.data1, MyClass.data2) for row in session.execute(select(bn)).where(bn.c.data1 == "d1"): print(row.mybundle["data1"], row.mybundle["data2"])
-
attribute
sqlalchemy.orm.Bundle.
is_aliased_class = False¶ 如果此对象是
AliasedClass
的实例,则为 True。
-
attribute
sqlalchemy.orm.Bundle.
is_bundle = True¶ 如果此对象是
Bundle
的实例,则为 True。
-
attribute
sqlalchemy.orm.Bundle.
is_clause_element = False¶ 如果此对象是
ClauseElement
的实例,则为 True。
-
attribute
sqlalchemy.orm.Bundle.
is_mapper = False¶ 如果此对象是
Mapper
的实例,则为 True。
-
method
sqlalchemy.orm.Bundle.
label(name)¶ 提供此
Bundle
的副本,并传递新的标签。
-
attribute
sqlalchemy.orm.Bundle.
single_entity = False¶ 如果为 True,则对单个 Bundle 的查询将作为单个实体返回,而不是键值元组中的元素返回。
-
method
- function sqlalchemy.orm.with_loader_criteria(entity_or_base: _EntityType[Any], where_criteria: _ColumnExpressionArgument[bool] | Callable[[Any], _ColumnExpressionArgument[bool]], loader_only: bool = False, include_aliases: bool = False, propagate_to_loaders: bool = True, track_closure_variables: bool = True) → LoaderCriteriaOption¶
为特定实体的所有出现次数的加载添加额外的 WHERE 条件。
1.4 版本新增。
with_loader_criteria()
选项旨在为查询中的特定类型的实体添加限制条件,全局地,这意味着它将应用于实体在 SELECT 查询中以及任何子查询、连接条件和关系加载(包括迫切加载和延迟加载)中的出现,而无需在查询的任何特定部分中指定它。渲染逻辑使用与单表继承相同的系统,以确保将某个鉴别器应用于表。例如,使用 2.0 风格 的查询,我们可以限制加载
User.addresses
集合的方式,无论使用何种加载方式from sqlalchemy.orm import with_loader_criteria stmt = select(User).options( selectinload(User.addresses), with_loader_criteria(Address, Address.email_address != "foo"), )
上面,
User.addresses
的 “selectinload” 将给定的过滤条件应用于 WHERE 子句。另一个示例,其中过滤将应用于连接的 ON 子句,在此示例中使用 1.x 风格 的查询
q = ( session.query(User) .outerjoin(User.addresses) .options(with_loader_criteria(Address, Address.email_address != "foo")) )
with_loader_criteria()
的主要目的是在SessionEvents.do_orm_execute()
事件处理程序中使用它,以确保以某种方式过滤特定实体的所有出现,例如按访问控制角色进行过滤。它也可以用于将条件应用于关系加载。在下面的示例中,我们可以将一组特定的规则应用于特定Session
发出的所有查询session = Session(bind=engine) @event.listens_for("do_orm_execute", session) def _add_filtering_criteria(execute_state): if ( execute_state.is_select and not execute_state.is_column_load and not execute_state.is_relationship_load ): execute_state.statement = execute_state.statement.options( with_loader_criteria( SecurityRole, lambda cls: cls.role.in_(["some_role"]), include_aliases=True, ) )
在上面的示例中,
SessionEvents.do_orm_execute()
事件将拦截使用Session
发出的所有查询。对于那些是 SELECT 语句且不是属性或关系加载的查询,自定义的with_loader_criteria()
选项被添加到查询中。with_loader_criteria()
选项将在给定的语句中使用,并且还将自动传播到从此查询派生的所有关系加载。给定的 criteria 参数是一个
lambda
,它接受一个cls
参数。给定的类将扩展为包括所有映射的子类,并且本身不必是映射的类。提示
当结合
contains_eager()
加载器选项使用with_loader_criteria()
选项时,重要的是要注意with_loader_criteria()
仅影响查询中确定在 WHERE 和 FROM 子句方面渲染哪些 SQL 的部分。contains_eager()
选项不影响 SELECT 语句在 columns 子句之外的渲染,因此与with_loader_criteria()
选项没有任何交互。然而,“工作” 方式是contains_eager()
旨在与已经以某种方式从附加实体中选择的查询一起使用,其中with_loader_criteria()
可以应用其附加条件。在下面的示例中,假设映射关系为
A -> A.bs -> B
,给定的with_loader_criteria()
选项将影响 JOIN 的渲染方式stmt = ( select(A) .join(A.bs) .options(contains_eager(A.bs), with_loader_criteria(B, B.flag == 1)) )
上面,给定的
with_loader_criteria()
选项将影响由.join(A.bs)
指定的 JOIN 的 ON 子句,因此按预期应用。contains_eager()
选项的效果是将B
中的列添加到 columns 子句中SELECT b.id, b.a_id, b.data, b.flag, a.id AS id_1, a.data AS data_1 FROM a JOIN b ON a.id = b.a_id AND b.flag = :flag_1
在上述语句中使用
contains_eager()
选项对with_loader_criteria()
选项的行为没有影响。如果省略contains_eager()
选项,则 SQL 在 FROM 和 WHERE 子句方面将是相同的,其中with_loader_criteria()
继续将其条件添加到 JOIN 的 ON 子句中。contains_eager()
的添加仅影响 columns 子句,因为添加了针对b
的附加列,然后 ORM 使用这些列来生成B
实例。警告
在调用
with_loader_criteria()
内部使用 lambda 仅针对每个唯一类调用一次。自定义函数不应在此 lambda 中调用。有关 “lambda SQL” 功能的概述,请参阅 使用 Lambdas 为语句生成增加显著的速度增益,该功能仅供高级使用。- 参数:
entity_or_base¶ – 应用规则的映射类,或作为特定映射类集合的超类的类。
where_criteria¶ –
应用限制条件的核心 SQL 表达式。当给定的类是具有许多不同映射子类的基类时,这也可以是接受目标类作为参数的 “lambda:” 或 Python 函数。
注意
为了支持 pickle,请使用模块级的 Python 函数来生成 SQL 表达式,而不是 lambda 或固定的 SQL 表达式,因为它们往往不可 pickle。
propagate_to_loaders¶ –
默认为 True,应用于关系加载器,例如延迟加载器。这表示选项对象本身(包括 SQL 表达式)随每个加载的实例一起携带。设置为
False
以防止对象被分配给单个实例。另请参阅
ORM 查询事件 - 包括使用
with_loader_criteria()
的示例。添加全局 WHERE / ON 条件 - 关于如何将
with_loader_criteria()
与SessionEvents.do_orm_execute()
事件结合使用的基本示例。track_closure_variables¶ –
当为 False 时,lambda 表达式内部的闭包变量将不作为任何缓存键的一部分使用。这允许在 lambda 表达式内部使用更复杂的表达式,但要求 lambda 确保每次给定特定类时都返回相同的 SQL。
1.4.0b2 版本新增。
- function sqlalchemy.orm.join(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, isouter: bool = False, full: bool = False) → _ORMJoin¶
在 left 和 right 子句之间生成内连接。
join()
是对join()
提供的核心 join 接口的扩展,其中 left 和 right selectable 不仅可以是核心 selectable 对象(例如Table
),还可以是映射类或AliasedClass
实例。“on” 子句可以是 SQL 表达式或引用配置的relationship()
的 ORM 映射属性。在现代用法中,通常不需要
join()
,因为它的功能封装在Select.join()
和Query.join()
方法中,这些方法的功能远超join()
本身所能提供的自动化程度。显式使用join()
和启用 ORM 的 SELECT 语句涉及使用Select.select_from()
方法,如下所示from sqlalchemy.orm import join stmt = ( select(User) .select_from(join(User, Address, User.addresses)) .filter(Address.email_address == "foo@bar.com") )
在现代 SQLAlchemy 中,上面的 join 可以更简洁地写成
stmt = ( select(User) .join(User.addresses) .filter(Address.email_address == "foo@bar.com") )
警告
直接使用
join()
可能无法与现代 ORM 选项(例如with_loader_criteria()
)正常工作。强烈建议在使用 ORM 连接时使用由Select.join()
和Select.join_from()
等方法提供的惯用 join 模式。
- function sqlalchemy.orm.outerjoin(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, full: bool = False) → _ORMJoin¶
在 left 和 right 子句之间生成左外连接。
这是
join()
函数的 “外连接” 版本,具有相同的行为,只是生成 OUTER JOIN。有关其他用法详细信息,请参阅该函数的文档。
- function sqlalchemy.orm.with_parent(instance: object, prop: attributes.QueryableAttribute[Any], from_entity: _EntityType[Any] | None = None) → ColumnElement[bool]¶
创建过滤条件,使用已建立的
relationship()
配置,将此查询的主实体与给定的相关实例关联起来。例如:
stmt = select(Address).where(with_parent(some_user, User.addresses))
渲染的 SQL 与从该属性上的给定父级触发延迟加载器时渲染的 SQL 相同,这意味着从 Python 中的父对象获取适当的状态,而无需在渲染的语句中渲染到父表的连接。
给定的 property 也可以使用
PropComparator.of_type()
来指示条件的左侧a1 = aliased(Address) a2 = aliased(Address) stmt = select(a1, a2).where(with_parent(u1, User.addresses.of_type(a2)))
上面的用法等效于使用
from_entity()
参数a1 = aliased(Address) a2 = aliased(Address) stmt = select(a1, a2).where( with_parent(u1, User.addresses, from_entity=a2) )
- 参数:
instance¶ – 具有某些
relationship()
的实例。property¶ – 类绑定的属性,指示应使用实例中的哪个关系来协调父/子关系。
from_entity¶ –
要考虑作为左侧的实体。这默认为
Query
本身的 “零” 实体。1.2 版本新增。
flambé! 龙和 The Alchemist 图像设计由 Rotem Yaari 创作并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档上次生成时间:Tue 11 Mar 2025 02:40:17 PM EDT