SQLAlchemy 2.0 文档
- 上一章: 关系加载技术
- 下一章: 传统查询 API
- 上一级: 首页
- 本页内容
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()
中记录的 Core 级别的执行选项。重要的是要注意,下面讨论的 ORM 选项与 Core 级别的 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
不调用“autoflush”步骤。这等效于使用 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
选项的目的是改变这种行为,以便 ORM 结果集针对迭代非常大的结果集(例如 > 10K 行)进行优化,在这些结果集中,用户已经确定上述模式不适用。当使用 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.yield_per()
方法,该方法在返回的 Result
对象上,该方法确定要获取的行数的固定大小以及对应于一次构建多少 ORM 对象的限制。
提示
yield_per
现在也可用作 Core 执行选项,在 使用服务器端游标(也称为流式结果) 中详细介绍。本节详细介绍了 yield_per
作为使用 ORM Session
的执行选项的使用。该选项在两种情况下尽可能地类似地工作。
当与 ORM 一起使用时,必须通过给定语句上的 Executable.execution_options()
方法或将其传递给 Session.execute.execution_options
参数的 Session.execute()
或其他类似的 Session
方法,例如 Session.scalars()
来建立 yield_per
。获取 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
Core 级别的执行选项以及 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
执行选项 **与** “子查询”预加载 加载或 “联接”预加载 加载(当使用集合时) **不兼容**。它可能与 “选择在”预加载 兼容,前提是数据库驱动程序支持多个独立的游标。
此外,yield_per
执行选项与 Result.unique()
方法 **不兼容**;因为此方法依赖于存储所有行的完整身份集,它必然会失去使用 yield_per
的意义,即处理任意数量的行。
在版本 1.4.6 中更改: 当从使用 Result.unique()
筛选器的 Result
对象中获取 ORM 行时,同时使用 yield_per
执行选项,将引发异常。
当使用旧版 Query
对象与 1.x 风格 ORM 使用时,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]
上面类别的默认“架构”名称是 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
类的主键 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“可选择项”相同。例如,在连接表继承方案中,"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。 |
|
提供 |
|
一个 SQL 表达式分组,这些表达式由 |
|
join(left, right[, onclause, isouter, ...]) |
在左侧和右侧子句之间生成内连接。 |
outerjoin(left, right[, onclause, full]) |
在左侧和右侧子句之间生成左外连接。 |
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)
The
aliased()
函数用于创建映射类到新可选择的临时映射。默认情况下,可选择项是使用通常映射的可选择项(通常是Table
)生成的,使用FromClause.alias()
方法。但是,aliased()
也可以用于将类链接到新的select()
语句。此外,with_polymorphic()
函数是aliased()
的变体,旨在指定一个所谓的“多态可选择项”,它对应于多个联接继承子类的并集。为了方便起见,
aliased()
函数还接受普通的FromClause
结构,例如Table
或select()
结构。在这些情况下,FromClause.alias()
方法将在对象上调用,并返回新的Alias
对象。在这种情况下,返回的Alias
未映射到 ORM。- 参数:
element¶ – 要设置别名的元素。通常是映射类,但为了方便起见,它也可以是
FromClause
元素。alias¶ – 可选的可选择项单元,用于将元素映射到该单元。这通常用于将对象链接到子查询,并且应该是从
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 实体的映射列映射到给定可选择项的映射列时,将使用更宽松的“匹配” - 如果给定可选择项没有与实体上的列相对应的列,则将执行基于名称的匹配。这在将实体与某些派生可选择项(例如使用聚合函数的可选择项)关联时,是该方法的用例。
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。
这是
alias()
结构的 ORM 等效项,该对象使用__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
也能够将现有的映射类映射到一个全新的可选择对象,前提是该可选择对象与现有的映射可选择对象在列方面兼容,并且它也可以在映射中配置为relationship()
的目标。有关示例,请参见下面的链接。AliasedClass
对象通常使用aliased()
函数构造。它在使用with_polymorphic()
函数时也会以额外的配置方式生成。生成的的对象是
AliasedClass
的实例。此对象实现了一个属性方案,该方案产生与原始映射类相同的属性和方法接口,允许AliasedClass
与任何在原始类上工作的属性技术兼容,包括混合属性(参见 混合属性)。AliasedClass
可以使用inspect()
检查其底层的Mapper
、别名可选择对象和其他信息。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
对象的检查接口。使用
inspect()
函数,在给定AliasedClass
的情况下返回AliasedInsp
对象。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
的选择结构中表达的所有映射器。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¶
一个 SQL 表达式分组,这些表达式由
Query
在一个命名空间下返回。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)
也支持包的嵌套
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
生成“行处理”函数。子类可以覆盖它,以便在获取结果时提供自定义行为。该方法在查询执行时传递语句对象和一组“行处理”函数;这些处理函数在给定结果行时将返回单个属性值,然后可以将其改编为任何类型的返回数据结构。
以下示例说明了用简单的 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()
选项将用于给定的语句中,并将自动传播到从该查询派生的所有关系加载。给定的条件参数是一个
lambda
,它接受一个cls
参数。给定的类将扩展到包括所有映射的子类,并且不需要本身是映射的类。提示
当在
with_loader_criteria()
选项与contains_eager()
加载器选项结合使用时,重要的是要注意with_loader_criteria()
仅影响查询中决定 WHERE 和 FROM 子句中渲染的 SQL 的部分。该contains_eager()
选项不会影响 SELECT 语句在列子句之外的渲染,因此不会与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
的列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()
仅影响列子句,因为会添加针对b
的额外列,然后由 ORM 使用这些列来生成B
实例。警告
在调用
with_loader_criteria()
中使用 lambda 仅针对**每个唯一类调用一次**。自定义函数不应在此 lambda 内调用。有关“lambda SQL”功能的概述,请参阅 使用 Lambdas 为语句生产增加显着的速度提升,该功能仅供高级用户使用。- 参数:
entity_or_base¶ – 映射的类,或作为特定映射类集合的超类的类,规则将应用于该类。
where_criteria¶ –
应用限制条件的 Core SQL 表达式。这也可以是接受目标类作为参数的“lambda:”或 Python 函数,当给定的类是具有许多不同映射子类的基类时。
注意
为了支持腌制,请使用模块级 Python 函数来生成 SQL 表达式,而不是 lambda 或固定的 SQL 表达式,这些表达式往往不能腌制。
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¶
在左侧和右侧子句之间生成内连接。
join()
是join()
提供的核心连接接口的扩展,其中左右可选择项不仅可以是核心可选择项对象(如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=='[email protected]')
在现代 SQLAlchemy 中,上面的连接可以更简洁地写成:
stmt = select(User).\ join(User.addresses).\ filter(Address.email_address=='[email protected]')
警告
直接使用
join()
可能无法与现代 ORM 选项(如with_loader_criteria()
)正常工作。强烈建议使用Select.join()
和Select.join_from()
等方法提供的惯用连接模式来创建 ORM 连接。
- function sqlalchemy.orm.outerjoin(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, full: bool = False) → _ORMJoin¶
在左侧和右侧子句之间生成左外连接。
这是
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 中的父级对象获取,而无需在渲染的语句中渲染到父级表的连接。
给定属性还可以使用
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é! 龙和 炼金术士 图像设计由 Rotem Yaari 创建并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档上次生成时间:2024 年 11 月 8 日星期五 上午 08:41:19 EST