SqlAlchemy 2.0 中文文档(二十四)(3)https://developer.aliyun.com/article/1560546
上下文会话 API
对象名称 | 描述 |
QueryPropertyDescriptor | 描述应用于类级别scoped_session.query_property() 属性的类型。 |
scoped_session | 提供Session 对象的作用域管理。 |
ScopedRegistry | 可以根据“作用域”函数存储单个类的一个或多个实例的注册表。 |
ThreadLocalRegistry | 使用threading.local() 变量进行存储的ScopedRegistry 。 |
class sqlalchemy.orm.scoped_session
提供Session
对象的作用域管理。
参见上下文/线程本地会话教程。
注意
在使用异步 I/O (asyncio)时,应该使用与scoped_session
类异步兼容的async_scoped_session
类。
成员
call(), init(), add(), add_all(), autoflush, begin(), begin_nested(), bind, bulk_insert_mappings(), bulk_save_objects(), bulk_update_mappings(), close(), close_all(), commit(), configure(), connection(), delete(), deleted, dirty, execute(), expire(), expire_all(), expunge(), expunge_all(), flush(), get(), get_bind(), get_one(), identity_key(), identity_map, info, is_active, is_modified(), merge(), new, no_autoflush, object_session(), query(), query_property(), refresh(), remove(), reset(), rollback(), scalar(), scalars(), session_factory
类签名
类sqlalchemy.orm.scoped_session
(typing.Generic
)
method __call__(**kw: Any) → _S
返回当前Session
,如果不存在,则使用scoped_session.session_factory
创建它。
参数:
**kw – 关键字参数将传递给scoped_session.session_factory
可调用对象,如果不存在现有的Session
。如果存在Session
并且已传递关键字参数,则会引发InvalidRequestError
。
method __init__(session_factory: sessionmaker[_S], scopefunc: Callable[[], Any] | None = None)
构建一个新的scoped_session
。
参数:
session_factory
– 一个用于创建新的Session
实例的工厂。通常情况下,但不一定,这是一个sessionmaker
的实例。scopefunc
– 可选函数,定义当前范围。如果未传递,scoped_session
对象假定“线程本地”范围,并将使用 Python 的threading.local()
来维护当前Session
。如果传递了函数,该函数应返回一个可散列的令牌;此令牌将用作字典中的键,以便存储和检索当前Session
。
method add(instance: object, _warn: bool = True) → None
将一个对象放入此Session
。
代表scoped_session
类的Session
类的代理。
当通过Session.add()
方法传递的对象处于瞬态状态时,它们将移动到挂起状态,直到下一次刷新,然后它们将移动到持久状态。
当通过Session.add()
方法传递的对象处于分离状态时,它们将直接移动到持久状态。
如果Session
使用的事务被回滚,则在它们被传递给Session.add()
时处于瞬态的对象将被移回瞬态状态,并且将不再存在于此Session
中。
另请参阅
Session.add_all()
添加新项目或现有项目 - 在使用会话基础知识中
method add_all(instances: Iterable[object]) → None
将给定的实例集添加到此Session
中。
代表scoped_session
类的Session
类的代理。
有关Session.add()
的一般行为描述,请参阅文档。
另请参阅
Session.add()
添加新项目或现有项目 - 在使用会话基础知识中
attribute autoflush
代表scoped_session
类的Session.autoflush
属性的代理。
method begin(nested: bool = False) → SessionTransaction
如果尚未开始事务,则在此Session
上开始事务或嵌套事务。
代表scoped_session
类的Session
类的代理。
Session
对象具有自动开始行为,因此通常不需要显式调用Session.begin()
方法。但是,它可以用于控制事务状态开始的范围。
当用于开始最外层事务时,如果此Session
已在事务内部,则会引发错误。
参数:
嵌套 - 如果为 True,则开始 SAVEPOINT 事务,并等效于调用Session.begin_nested()
。有关 SAVEPOINT 事务的文档,请参阅使用 SAVEPOINT。
返回:
SessionTransaction
对象。请注意,SessionTransaction
充当 Python 上下文管理器,允许在“with”块中使用Session.begin()
。请参阅显式开始获取示例。
另请参阅
自动开始
管理事务
Session.begin_nested()
method begin_nested() → SessionTransaction
在此 Session 上开始一个“嵌套”事务,例如 SAVEPOINT。
代理 scoped_session
类的 Session
类。
目标数据库及其关联的驱动程序必须支持 SQL SAVEPOINT,该方法才能正确运行。
有关 SAVEPOINT 事务的文档,请参阅使用 SAVEPOINT。
返回:
SessionTransaction
对象。请注意,SessionTransaction
作为上下文管理器,允许在“with”块中使用 Session.begin_nested()
。有关用法示例,请参阅使用 SAVEPOINT。
另请参阅
使用 SAVEPOINT
Serializable isolation / Savepoints / Transactional DDL - 为了使 SAVEPOINT 正确工作,SQLite 驱动程序需要特殊的解决方法。对于 asyncio 用例,请参阅 Serializable isolation / Savepoints / Transactional DDL(asyncio 版本) 部分。
attribute bind
代理 scoped_session
类的 Session.bind
属性。
method bulk_insert_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]], return_defaults: bool = False, render_nulls: bool = False) → None
对给定的映射字典列表执行批量插入。
代理 scoped_session
类的 Session
类。
传统功能
此方法是 SQLAlchemy 2.0 系列的传统功能。对于现代批量插入和更新,请参阅 ORM 批量 INSERT 语句 和 ORM 根据主键批量更新。2.0 API 与此方法共享实现细节,并添加了新功能。
参数:
mapper
- 一个映射类,或者实际的Mapper
对象,表示映射列表中表示的单个对象类型。mappings
– 一个字典序列,每个字典包含要插入的映射行的状态,以映射类上的属性名称表示。如果映射引用多个表,例如联合继承映射,每个字典必须包含要填充到所有表中的所有键。return_defaults
–
当设置为 True 时,将更改 INSERT 过程以确保获取新生成的主键值。通常设置此参数的原因是启用联合表继承映射的批量插入。
注意
对于不支持 RETURNING 的后端,Session.bulk_insert_mappings.return_defaults
参数可以显著降低性能,因为无法批量处理 INSERT 语句。请参阅 “插入多个值”行为的 INSERT 语句 了解哪些后端会受到影响的背景信息。render_nulls
–
当设置为 True 时,None
的值将导致 NULL 值包含在 INSERT 语句中,而不是将列从 INSERT 中省略。这允许要 INSERT 的所有行具有相同的列集,从而允许将所有行批量发送到 DBAPI。通常,包含与上一行不同的 NULL 值组合的每个列集必须省略 INSERT 语句中的一系列不同列,这意味着必须将其作为单独的语句发出。通过传递此标志,可以确保将所有行的完整集合批量处理到一个批次中;但是,成本是将被省略的列调用的服务器端默认值将被跳过,因此必须确保这些值不是必需的。
警告
当设置此标志时,不会为那些以 NULL 插入的列调用服务器端默认 SQL 值;NULL 值将被明确发送。必须小心确保整个操作不需要调用服务器端默认函数。
请参阅
ORM 启用的 INSERT、UPDATE 和 DELETE 语句
Session.bulk_save_objects()
Session.bulk_update_mappings()
method bulk_save_objects(objects: Iterable[object], return_defaults: bool = False, update_changed_only: bool = True, preserve_order: bool = True) → None
对给定对象列表执行批量保存。
代理Session
类,代表scoped_session
类。
旧特性
此方法作为 SQLAlchemy 2.0 系列的传统功能。有关现代批量 INSERT 和 UPDATE,请参见 ORM 批量 INSERT 语句和 ORM 批量按主键 UPDATE 部分。
对于一般的 ORM 映射对象的 INSERT 和 UPDATE,请优先使用标准的工作单元数据管理模式,在 SQLAlchemy 统一教程的 ORM 数据操作中引入。SQLAlchemy 2.0 现在使用现代方言的“Insert Many Values”行为用于 INSERT 语句,解决了以前批量 INSERT 速度慢的问题。
参数:
objects
–
一个映射对象实例的序列。映射对象按原样持久化,并且在之后不与Session
相关联。
对于每个对象,该对象是作为 INSERT 还是 UPDATE 发送取决于传统操作中Session
使用的相同规则;如果对象具有InstanceState.key
属性设置,则假定对象为“分离”,并将导致 UPDATE。否则,使用 INSERT。
在 UPDATE 的情况下,语句根据已更改的属性分组,因此将成为每个 SET 子句的主题。如果update_changed_only
为 False,则将应用每个对象中存在的所有属性到 UPDATE 语句中,这可能有助于将语句分组到更大的 executemany()中,并且还将减少检查属性历史记录的开销。return_defaults
– 当为 True 时,将缺少生成默认值的值的行插入“一次”,以便主键值可用。特别是,这将允许联合继承和其他多表映射正确插入,而无需提前提供主键值;但是,Session.bulk_save_objects.return_defaults
大大降低了
该方法的性能收益。强烈建议请使用标准的Session.add_all()
方法。update_changed_only
– 当为 True 时,基于每个状态中已记录更改的属性渲染 UPDATE 语句。当为 False 时,除主键属性外,将所有存在的属性渲染到 SET 子句中。preserve_order
- 当为 True 时,插入和更新的顺序与给定对象的顺序完全匹配。当为 False 时,常见类型的对象被分组为插入和更新,以便提供更多的批处理机会。
另请参阅
ORM-Enabled INSERT、UPDATE 和 DELETE 语句
Session.bulk_insert_mappings()
Session.bulk_update_mappings()
method bulk_update_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]]) → None
对给定的映射字典列表执行批量更新。
代理了scoped_session
类的Session
类。
传统功能
作为 SQLAlchemy 2.0 系列的一个传统功能。有关现代批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句和 ORM 通过主键进行批量 UPDATE 部分。2.0 API 与此方法共享实现细节,并添加了新功能。
参数:
mapper
- 一个映射类,或者表示映射列表中所表示的单一对象的实际Mapper
对象。mappings
- 一系列字典,每个字典包含要更新的映射行的状态,以映射类上的属性名称为准。如果映射涉及多个表,比如联接继承映射,则每个字典可能包含对所有表对应的键。所有这些已存在且不是主键的键都将应用于 UPDATE 语句的 SET 子句;所需的主键值将应用于 WHERE 子句。
另请参阅
ORM-Enabled INSERT、UPDATE 和 DELETE 语句
Session.bulk_insert_mappings()
Session.bulk_save_objects()
method close() → None
关闭此Session
所使用的事务资源和 ORM 对象。
代理了scoped_session
类的Session
类。
这会清除与此Session
关联的所有 ORM 对象,结束任何正在进行的事务,并释放此Session
自身从关联的Engine
对象中签出的任何Connection
对象。然后,该操作将使Session
处于可以再次使用的状态。
提示
在默认运行模式下,Session.close()
方法不会阻止再次使用会话。Session
本身实际上没有明确的“关闭”状态;它只是表示Session
将释放所有数据库连接和 ORM 对象。
将参数Session.close_resets_only
设置为False
将使close
最终,意味着会禁止对会话的任何进一步操作。
从版本 1.4 开始更改:Session.close()
方法不会立即创建新的SessionTransaction
对象;只有在再次为数据库操作使用Session
时才会创建新的SessionTransaction
。
另请参见
关闭 - 关于Session.close()
和Session.reset()
语义的详细信息。
Session.reset()
- 一个类似的方法,行为类似于close()
,参数Session.close_resets_only
设置为True
。
classmethod close_all() → None
关闭所有内存中的会话。
代理scoped_session
类的Session
类。
自 1.3 版本起已弃用:Session.close_all()
方法已弃用,将在将来的版本中删除。请参考close_all_sessions()
。
method commit() → None
刷新待处理更改并提交当前事务。
代理了scoped_session
类的Session
类。
当 COMMIT 操作完成时,所有对象都被完全过期,擦除其内部内容,在下次访问对象时会自动重新加载。在此期间,这些对象处于过期状态,如果从Session
中分离,它们将无法运行。此外,在使用基于 asyncio 的 API 时不支持此重新加载操作。Session.expire_on_commit
参数可用于禁用此行为。
当Session
没有正在进行的事务时,表示自上次调用Session.commit()
以来没有对此Session
进行任何操作,则该方法将开始并提交一个仅限内部的“逻辑”事务,通常不会影响数据库,除非检测到待处理的刷新更改,但仍将调用事件处理程序和对象过期规则。
最外层数据库事务会无条件提交,自动释放任何正在进行的 SAVEPOINT。
请参阅。
提交。
管理事务。
在使用 AsyncSession 时避免隐式 IO。
method configure(**kwargs: Any) → None
重新配置由此scoped_session
使用的sessionmaker
。
查看sessionmaker.configure()
。
method connection(bind_arguments: _BindArguments | None = None, execution_options: CoreExecuteOptionsParameter | None = None) → Connection
返回一个对应于此Session
对象的事务状态的Connection
对象。
代理了scoped_session
类的Session
类。
返回当前事务对应的Connection
,如果没有进行中的事务,则开始一个新事务并返回Connection
(注意,直到发出第一个 SQL 语句之前,才会与 DBAPI 建立事务状态)。
多绑定或未绑定的Session
对象中的歧义可以通过任何可选的关键字参数来解决。最终,这使得使用get_bind()
方法来解析。
参数:
bind_arguments
– 绑定参数字典。可能包括“mapper”、“bind”、“clause”、“其他传递给Session.get_bind()
的自定义参数。execution_options
–
将传递给Connection.execution_options()
的执行选项字典,仅在首次获取连接时。如果连接已经存在于Session
中,则会发出警告并忽略参数。
另请参阅
设置事务隔离级别 / DBAPI AUTOCOMMIT
method delete(instance: object) → None
将实例标记为已删除。
代表scoped_session
类为Session
类代理。
当传递的对象被假定为持久的或分离的时,调用该方法后,对象将保持在持久状态,直到下一次刷新进行。在此期间,该对象还将成为Session.deleted
集合的成员。
下一次刷新进行时,对象将转移到删除状态,表示在当前事务中为其行发出了DELETE
语句。当事务成功提交时,已删除的对象将转移到分离状态,并且不再存在于此Session
中。
另请参阅
删除 - 在使用会话的基础知识
attribute deleted
所有在此Session
中标记为“已删除”的实例集合
代表scoped_session
类为Session
类进行了代理。
attribute dirty
被视为脏的所有持久实例的集合。
代表scoped_session
类为Session
类进行了代理。
例如:
some_mapped_object in session.dirty
实例在被修改但未被删除时被视为脏。
请注意,这个“脏”计算是“乐观”的;大多数属性设置或集合修改操作都会将实例标记为“脏”,并将其放入这个集合中,即使属性的值没有净变化。在刷新时,将每个属性的值与其先前保存的值进行比较,如果没有净变化,则不会发生 SQL 操作(这是一项更昂贵的操作,因此只在刷新时执行)。
要检查实例是否对其属性有可操作的净变化,请使用Session.is_modified()
方法。
method execute(statement: Executable, params: _CoreAnyExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, _parent_execute_state: Any | None = None, _add_event: Any | None = None) → Result[Any]
执行 SQL 表达式构造。
代表scoped_session
类为Session
类进行了代理。
返回表示语句执行结果的Result
对象。
例如:
from sqlalchemy import select result = session.execute( select(User).where(User.id == 5) )
Session.execute()
的 API 合同类似于Connection.execute()
,2.0 风格版本的Connection
。
从版本 1.4 开始变更:当使用 2.0 风格 ORM 使用时,Session.execute()
方法现在是 ORM 语句执行的主要点。
参数:
statement
– 可执行的语句(即Executable
表达式,如select()
)。params
– 可选字典或字典列表,其中包含绑定的参数值。如果是单个字典,则执行单行操作;如果是字典列表,则将调用“executemany”。每个字典中的键必须对应于语句中存在的参数名称。execution_options
–
可选的执行选项字典,将与语句执行相关联。此字典可以提供Connection.execution_options()
接受的选项子集,并且还可以提供只在 ORM 上下文中理解的其他选项。
另请参阅
ORM 执行选项 - ORM 特定的执行选项bind_arguments
– 用于确定绑定的其他参数的字典。可能包括“mapper”,“bind”或其他自定义参数。此字典的内容传递给Session.get_bind()
方法。
返回:
一个Result
对象。
method expire(instance: object, attribute_names: Iterable[str] | None = None) → None
将实例的属性过期。
代表scoped_session
类的Session
类的代理。
将实例的属性标记为过时。下次访问过期属性时,将向Session
对象的当前事务上下文发出查询,以加载给定实例的所有过期属性。请注意,高度隔离的事务将返回与先前在同一事务中读取的相同值,而不管该事务之外的数据库状态的变化。
要同时使Session
中的所有对象过期,请使用Session.expire_all()
。
Session
对象的默认行为是在调用Session.rollback()
或Session.commit()
方法时将所有状态过期,以便为新的事务加载新状态。因此,仅在当前事务中发出了非 ORM SQL 语句的特定情况下调用Session.expire()
才有意义。
参数:
instance
– 要刷新的实例。attribute_names
– 可选的字符串属性名称列表,指示要过期的属性子集。
另请参阅
刷新 / 过期 - 入门材料
Session.expire()
Session.refresh()
Query.populate_existing()
method expire_all() → None
使此会话中的所有持久实例过期。
代表 scoped_session
类,为 Session
类提供代理。
当下次访问持久实例的任何属性时,将使用 Session
对象的当前事务上下文发出查询,以加载给定实例的所有过期属性。请注意,高度隔离的事务将返回与之前在该事务中读取的相同值,而不考虑该事务之外的数据库状态的更改。
要使单个对象和这些对象上的单个属性过期,请使用 Session.expire()
。
Session
对象的默认行为是在调用 Session.rollback()
或 Session.commit()
方法时使所有状态过期,以便为新事务加载新状态。因此,通常不需要调用 Session.expire_all()
,假设事务是隔离的。
另请参阅
刷新 / 过期 - 入门材料
Session.expire()
Session.refresh()
Query.populate_existing()
method expunge(instance: object) → None
从此 Session
中移除实例。
代表 scoped_session
类,为 Session
类提供代理。
这将释放对实例的所有内部引用。将根据 expunge 级联规则应用级联。
method expunge_all() → None
从此 Session
中移除所有对象实例。
代表 scoped_session
类,为 Session
类提供代理。
这相当于在此 Session
中对所有对象调用 expunge(obj)
。
method flush(objects: Sequence[Any] | None = None) → None
将所有对象更改刷新到数据库。
代表Session
类的scoped_session
类。
将所有待处理的对象创建、删除和修改写入数据库,作为 INSERTs、DELETEs、UPDATEs 等。操作会自动按照会话的工作单元依赖解析器进行排序。
数据库操作将在当前事务上下文中发出,并且不会影响事务的状态,除非发生错误,在这种情况下,整个事务都将回滚。您可以在事务中随意刷新()以将更改从 Python 移动到数据库的事务缓冲区。
参数:
objects –
可选;限制刷新操作仅对给定集合中存在的元素进行操作。
此功能适用于极为狭窄的一组使用案例,其中可能需要在完全刷新()发生之前对特定对象进行操作。不适用于常规用途。
method get(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options: Sequence[ORMOption] | None = None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token: Any | None = None, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None) → _O | None
返回基于给定主键标识符的实例,如果找不到则返回None
。
代表Session
类的scoped_session
类。
例如:
my_user = session.get(User, 5) some_object = session.get(VersionedFoo, (5, 10)) some_object = session.get( VersionedFoo, {"id": 5, "version_id": 10} )
从版本 1.4 开始:添加了Session.get()
,它已从现在的遗留Query.get()
方法中移动。
Session.get()
是特殊的,它直接提供对Session
的标识映射的访问。如果给定的主键标识符存在于本地标识映射中,则直接从此集合返回对象,并且不会发出 SQL,除非对象已被标记为完全过期。如果不存在,则执行 SELECT 以定位对象。
Session.get()
还将执行检查,看对象是否存在于标识映射中并标记为过期 - 还会发出 SELECT 以刷新对象以及确保行仍然存在。如果不是,则引发ObjectDeletedError
。
参数:
entity
– 指示要加载的实体类型的映射类或Mapper
。ident
–
代表主键的标量、元组或字典。对于复合(例如,多列)主键,应传递元组或字典。
对于单列主键,标量调用形式通常是最方便的。如果一行的主键是值“5”,调用看起来像:
my_object = session.get(SomeClass, 5)
- 元组形式包含主键值,通常按照其对应于映射的
Table
对象的主键列的顺序排列,或者如果使用了Mapper.primary_key
配置参数,则按照该参数使用的顺序排列。例如,如果一行的主键由整数数字“5, 10”表示,调用将如下所示:
my_object = session.get(SomeClass, (5, 10))
- 字典形式应包含键,对应于每个主键元素的映射属性名称。如果映射类具有存储对象主键值的属性
id
、version_id
,则调用将如下所示:
my_object = session.get(SomeClass, {"id": 5, "version_id": 10})
options
– 可选的加载器选项序列,如果发出查询,则将应用于该查询。populate_existing
– 导致该方法无条件发出 SQL 查询并使用新加载的数据刷新对象,无论对象是否已存在。with_for_update
– 可选布尔值True
,表示应该使用 FOR UPDATE,或者可以是一个包含标志的字典,表示用于 SELECT 的一组更具体的 FOR UPDATE 标志;标志应该与Query.with_for_update()
方法的参数匹配。取代Session.refresh.lockmode
参数。execution_options
–
可选的执行选项字典,如果发出查询,则与查询执行相关联。此字典可以提供Connection.execution_options()
接受的选项子集,并且还可以提供只在 ORM 上下文中理解的其他选项。
从版本 1.4.29 开始新增。
另请参阅
ORM 执行选项 - ORM 特定的执行选项bind_arguments
–
用于确定绑定的附加参数字典。可能包括“mapper”、“bind”或其他自定义参数。此字典的内容传递给Session.get_bind()
方法。
返回:
对象实例,或 None
。
method get_bind(mapper: _EntityBindKey[_O] | None = None, *, clause: ClauseElement | None = None, bind: _SessionBind | None = None, _sa_skip_events: bool | None = None, _sa_skip_for_implicit_returning: bool = False, **kw: Any) → Engine | Connection
返回此Session
绑定的“bind”。
代理为Session
类,代表scoped_session
类。
“bind”通常是 Engine
的实例,除非 Session
已经被明确地直接绑定到 Connection
的情况除外。
对于多重绑定或未绑定的 Session
,使用 mapper
或 clause
参数来确定要返回的适当绑定。
注意,当通过 ORM 操作调用 Session.get_bind()
,比如 Session.query()
,以及 Session.flush()
中的每个单独的 INSERT/UPDATE/DELETE 操作时,“mapper”参数通常会出现在调用中。
解析顺序为:
- 如果给定了 mapper 并且
Session.binds
存在,则根据首先使用的 mapper,然后使用的 mapped class,然后使用 mapped class 的__mro__
中存在的任何基类来定位绑定,从更具体的超类到更一般的超类。 - 如果给定了 clause 并且存在
Session.binds
,则根据Session.binds
中存在的给定 clause 中的Table
对象来定位绑定。 - 如果存在
Session.binds
,则返回该绑定。 - 如果给定了 clause,则尝试返回与 clause 最终关联的元数据的绑定。
- 如果给定了 mapper,则尝试返回与 mapper 映射到的
Table
或其他可选择的元数据最终关联的绑定。 - 如果找不到绑定,则会引发
UnboundExecutionError
。
注意,Session.get_bind()
方法可以在 Session
的用户定义的子类上被覆盖,以提供任何类型的绑定解析方案。请参阅自定义垂直分区中的示例。
参数:
mapper
– 可选的映射类或相应的Mapper
实例。绑定可以首先通过查看与此Session
相关联的“绑定”映射来派生自Mapper
,其次是通过查看与Mapper
映射到的Table
相关联的MetaData
来派生绑定。clause
– 一个ClauseElement
(即select()
、text()
等)。如果未提供mapper
参数或无法生成绑定,则将搜索给定的表达式构造以获取绑定元素,通常是与绑定的MetaData
相关联的Table
。
另请参阅
分区策略(例如每个会话的多个数据库后端)
Session.binds
Session.bind_mapper()
Session.bind_table()
method get_one(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options: Sequence[ORMOption] | None = None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token: Any | None = None, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None) → _O
基于给定的主键标识符返回一个实例,如果找不到则引发异常。
代表scoped_session
类的Session
类的代理。
如果查询未选择任何行,则引发sqlalchemy.orm.exc.NoResultFound
异常。
查看有关参数的详细文档,请参阅方法Session.get()
。
2.0.22 版中的新功能。
返回:
对象实例。
另请参阅
Session.get()
- 相应的方法,用于
如果找不到提供的主键的行,则返回None
。
classmethod identity_key(class_: Type[Any] | None = None, ident: Any | Tuple[Any, ...] = None, *, instance: Any | None = None, row: Row[Any] | RowMapping | None = None, identity_token: Any | None = None) → _IdentityKeyType[Any]
返回一个标识键。
代表scoped_session
类的Session
类的代理。
这是identity_key()
的别名。
attribute identity_map
代表scoped_session
类的Session.identity_map
属性的代理。
attribute info
用户可修改的字典。
代表scoped_session
类的Session
类的代理。
此字典的初始值可以使用Session
构造函数或sessionmaker
构造函数或工厂方法中的info
参数进行填充。此处的字典始终局限于此Session
并且可以独立于所有其他Session
对象进行修改。
attribute is_active
如果此Session
不处于“部分回滚”状态,则返回 True。
代表scoped_session
类的Session
类的代理。
从版本 1.4 开始更改:Session
不再立即开始新事务,因此在首次实例化Session
时,此属性将为 False。
“部分回滚”状态通常表示Session
的刷新过程失败,并且必须发出Session.rollback()
方法以完全回滚事务。
如果此Session
根本不处于事务中,则在首次使用时Session
将自动开始,因此在这种情况下Session.is_active
将返回 True。
否则,如果此Session
在事务中,并且该事务尚未在内部回滚,则Session.is_active
也将返回 True。
另请参阅
“由于刷新期间先前的异常,此会话的事务已回滚。”(或类似)
Session.in_transaction()
method is_modified(instance: object, include_collections: bool = True) → bool
如果给定实例具有本地修改的属性,则返回True
。
代理scoped_session
类为Session
类。
此方法检索实例上每个受检的属性的历史记录,并将当前值与其先前提交的值进行比较(如果有)。
这实际上是对在Session.dirty
集合中检查给定实例的更昂贵且准确的版本;会执行每个属性净“脏”状态的完整测试。
例如:
return session.is_modified(someobject
此方法有一些注意事项适用:
- 在
Session.dirty
集合中存在的实例在使用此方法进行测试时可能报告False
。这是因为对象可能已经通过属性变异接收到更改事件,从而将其放置在Session.dirty
中,但最终状态与从数据库加载的状态相同,在此处没有净变化。 - 当应用新值时,如果标量属性未加载或已过期,则可能未记录先前设置的值 - 在这些情况下,即使最终对其数据库值没有净变化,也假定属性已更改。大多数情况下,SQLAlchemy 在设置事件发生时不需要“旧”值,因此如果旧值不存在,则会跳过 SQL 调用的开销,这基于以下假设:标量值通常需要更新,在那些几种情况中不需要,平均而言比发出防御性 SELECT 要便宜。
只有在属性容器的active_history
标志设置为True
时,才会无条件地在设置时获取“旧”值。通常为主键属性和不是简单多对一的标量对象引用设置此标志。要为任意映射列设置此标志,请使用带有column_property()
的active_history
参数。
参数:
instance
– 要测试的映射实例的待处理更改。include_collections
– 表示是否应该包含多值集合在操作中。将其设置为False
是一种仅检测基于本地列的属性(即标量列或多对一外键)的方法,这些属性在刷新时会导致此实例的更新。
method merge(instance: _O, *, load: bool = True, options: Sequence[ORMOption] | None = None) → _O
将给定实例的状态复制到此Session
中的相应实例。
代理为scoped_session
类代表Session
类。
Session.merge()
检查源实例的主键属性,并尝试将其与会话中具有相同主键的实例进行协调。如果在本地找不到,它将尝试根据主键从数据库加载对象,如果找不到,则创建一个新实例。然后将源实例上的每个属性的状态复制到目标实例。然后方法返回生成的目标实例;如果原始源实例尚未关联,则保持不变且未关联Session
。
此操作如果关联映射使用cascade="merge"
,将级联到关联的实例。
有关合并的详细讨论,请参阅合并。
参数:
instance
– 要合并的实例。load
–
布尔值,当为 False 时,merge()
切换到“高性能”模式,导致它放弃发出历史事件以及所有数据库访问。此标志用于诸如从二级缓存传输对象图到Session
,或将刚加载的对象传输到工作线程或进程拥有的Session
中而无需重新查询数据库的情况。load=False
的用例添加了一个警告,即给定对象必须处于“干净”状态,即没有要刷新的挂起更改 - 即使传入对象与任何Session
都分离。这样,当合并操作填充本地属性并级联到相关对象和集合时,值可以“盖章”到目标对象上,而不会生成任何历史或属性事件,并且不需要将传入数据与可能未加载的任何现有相关对象或集合进行协调。load=False
的结果对象始终以“干净”方式生成,因此只有给定对象也应该“干净”,否则这表明方法的误用。options
–
可选的加载器选项序列,将在合并操作从数据库加载现有对象的版本时应用于Session.get()
方法。
1.4.24 版本中新增。
另请参阅
make_transient_to_detached()
- 提供了将单个对象“合并”到Session
中的替代方法
attribute new
在此Session
中标记为“新”的所有实例的集合。
代表scoped_session
类的Session
类的代理。
attribute no_autoflush
返回一个禁用自动刷新的上下文管理器。
代表scoped_session
类的Session
类的代理。
例如:
with session.no_autoflush: some_object = SomeClass() session.add(some_object) # won't autoflush some_object.related_thing = session.query(SomeRelated).first()
在with:
块内进行的操作不会受到查询访问时发生的刷新的影响。这在初始化涉及现有数据库查询的一系列对象时非常有用,其中未完成的对象不应立即被刷新。
classmethod object_session(instance: object) → Session | None
返回一个对象所属的Session
。
代表scoped_session
类的Session
类的代理。
这是object_session()
的别名。
method query(*entities: _ColumnsClauseArgument[Any], **kwargs: Any) → Query[Any]
返回与此Session
对应的新Query
对象。
代表scoped_session
类的Session
类的代理。
注意Query
对象在 SQLAlchemy 2.0 中已被废弃;现在使用select()
构造 ORM 查询。
另请参阅
SQLAlchemy 统一教程
ORM 查询指南
旧版查询 API - 旧版 API 文档
method query_property(query_cls: Type[Query[_T]] | None = None) → QueryPropertyDescriptor
返回一个类属性,当调用时会针对该类和当前Session
产生一个旧版的Query
对象。
旧版特性
scoped_session.query_property()
访问器专门针对传统的 Query
对象,不被视为 2.0-style ORM 使用的一部分。
例如:
from sqlalchemy.orm import QueryPropertyDescriptor from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker Session = scoped_session(sessionmaker()) class MyClass: query: QueryPropertyDescriptor = Session.query_property() # after mappers are defined result = MyClass.query.filter(MyClass.name=='foo').all()
默认情况下,通过会话配置的查询类产生会话的实例。要覆盖并使用自定义实现,请提供一个 query_cls
可调用对象。将使用类的映射器作为位置参数和会话关键字参数调用可调用对象。
在类上放置的查询属性的数量没有限制。
method refresh(instance: object, attribute_names: Iterable[str] | None = None, with_for_update: ForUpdateParameter = None) → None
对给定实例的过期和刷新属性。
代理为 scoped_session
类代表 Session
类。
选定的属性将首先过期,就像使用 Session.expire()
时一样;然后将向数据库发出 SELECT 语句,以使用当前事务中可用的当前值刷新面向列的属性。
如果对象已经急加载了,那么 relationship()
导向的属性也将立即加载,并使用它们最初加载的急加载策略。
新版本 1.4 中:- Session.refresh()
方法现在也可以刷新急加载的属性。
如果惰性加载的关系不在 Session.refresh.attribute_names
中命名,则它们将保持为“惰性加载”属性,并且不会隐式刷新。
2.0.4 版本中的更改:Session.refresh()
方法现在将刷新那些在 Session.refresh.attribute_names
集合中显式命名的惰性加载的 relationship()
导向的属性。
提示
虽然 Session.refresh()
方法能够刷新列和关系导向属性,但其主要焦点是在单个实例上刷新本地列导向属性。对于更开放式的“刷新”功能,包括在具有显式控制关系加载器策略的同时刷新多个对象的属性的能力,请改用 populate existing 功能。
注意,高度隔离的事务将返回在同一事务中先前读取的相同值,而不管该事务外部数据库状态的变化如何。刷新属性通常只在事务开始时有意义,此时数据库行尚未被访问。
参数:
attribute_names
– 可选。一个字符串属性名称的可迭代集合,指示要刷新的属性的子集。with_for_update
– 可选布尔值True
,表示应该使用 FOR UPDATE,或者可以是一个包含标志的字典,指示要在 SELECT 中使用一组更具体的 FOR UPDATE 标志;标志应该与Query.with_for_update()
的参数匹配。覆盖Session.refresh.lockmode
参数。
另请参阅
Refreshing / Expiring - 入门材料
Session.expire()
Session.expire_all()
Populate Existing - 允许任何 ORM 查询按照正常加载的方式刷新对象。
method remove() → None
如果存在,释放当前 Session
。
这首先会在当前 Session
上调用 Session.close()
方法,释放仍在持有的任何现有的事务/连接资源;具体地,会回滚事务。然后丢弃 Session
。在同一作用域内的下一次使用时,scoped_session
将生成一个新的 Session
对象。
method reset() → None
结束此 Session
使用的事务资源和 ORM 对象,将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会…
代理Session
类,代表scoped_session
类。
此方法提供了与Session.close()
方法历史上提供的相同的“仅重置”行为,其中Session
的状态被重置,就像对象是全新的,准备好再次使用一样。然后,此方法可能对将Session.close_resets_only
设置为False
的Session
对象有用,以便“仅重置”行为仍然可用。
新版本 2.0.22 中的内容。
另请参阅
关闭 - 关于Session.close()
和Session.reset()
语义的详细信息。
Session.close()
- 当参数Session.close_resets_only
设置为False
时,类似的方法还会阻止对会话的重新使用。
method rollback() → None
回滚当前进行中的事务。
代理Session
类,代表scoped_session
类。
如果没有事务正在进行,则此方法将被忽略。
该方法总是回滚最顶层的数据库事务,丢弃可能正在进行的任何嵌套事务。
另请参阅
回滚
管理事务
method scalar(statement: Executable, params: _CoreSingleExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) → Any
执行语句并返回标量结果。
代理Session
类,代表scoped_session
类。
使用方法和参数与Session.execute()
相同;返回结果是一个标量 Python 值。
method scalars(statement: Executable, params: _CoreAnyExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) → ScalarResult[Any]
执行语句并将结果作为标量返回。
代理Session
类,代表scoped_session
类。
使用和参数与 Session.execute()
相同;返回结果是一个过滤对象 ScalarResult
,该对象将返回单个元素而不是 Row
对象。
返回:
一个 ScalarResult
对象
新特性在版本 1.4.24 中添加:增加了 Session.scalars()
新特性在版本 1.4.26 中添加:增加了scoped_session.scalars()
另见
选择 ORM 实体 - 将Session.execute()
的行为与Session.scalars()
进行对比
attribute session_factory: sessionmaker[_S]
提供给 __init__
的 session_factory 存储在这个属性中,以后可以访问。当需要一个新的非范围 Session
时,这可能会很有用。
class sqlalchemy.util.ScopedRegistry
一个可以基于“作用域”函数存储一个或多个单个类实例的注册表。
该对象实现了 __call__
作为“getter”,因此通过调用 myregistry()
返回当前范围的包含对象。
参数:
createfunc
– 一个可调用的函数,返回要放置在注册表中的新对象scopefunc
– 一个可调用的函数,它将返回一个用于存储/检索对象的键。
成员
init(), clear(), has(), set()
类签名
类 sqlalchemy.util.ScopedRegistry
(typing.Generic
)
method __init__(createfunc: Callable[[], _T], scopefunc: Callable[[], Any])
构建一个新的 ScopedRegistry
。
参数:
createfunc
– 一个创建函数,如果当前范围中不存在,则会生成一个新值。scopefunc
– 返回表示当前范围的可哈希令牌的函数(例如,当前线程标识符)。
method clear() → None
清除当前范围,如果有的话。
method has() → bool
如果对象存在于当前范围中,则返回 True。
method set(obj: _T) → None
设置当前范围的值。
class sqlalchemy.util.ThreadLocalRegistry
使用 threading.local()
变量进行存储的 ScopedRegistry
。
类签名
类sqlalchemy.util.ThreadLocalRegistry
(sqlalchemy.util.ScopedRegistry
)
class sqlalchemy.orm.QueryPropertyDescriptor
描述应用于类级别的scoped_session.query_property()
属性的类型。
新版本 2.0.5 中新增。
类签名
类sqlalchemy.orm.QueryPropertyDescriptor
(typing_extensions.Protocol
)
隐式方法访问
scoped_session
的工作很简单;为所有请求它的人保存一个Session
。为了更透明地访问这个Session
,scoped_session
还包括代理行为,意味着可以直接将注册表本身视为Session
;当在这个对象上调用方法时,它们会被代理到注册表维护的基础Session
上:
Session = scoped_session(some_factory) # equivalent to: # # session = Session() # print(session.scalars(select(MyClass)).all()) # print(Session.scalars(select(MyClass)).all())
上述代码完成了与通过调用注册表获取当前Session
相同的任务,然后使用该Session
。
线程本地作用域
对于熟悉多线程编程的用户来说,将任何东西表示为全局变量通常都是一个坏主意,因为这意味着全局对象将被许多线程同时访问。Session
对象完全设计成以非并发方式使用,从多线程的角度来看,这意味着“一次只能在一个线程中”。因此,我们上面的scoped_session
使用示例,其中同一个Session
对象在多个调用之间保持不变,表明需要有一些进程存在,以确保许多线程中的多个调用实际上不会获得相同的会话句柄。我们将此概念称为线程本地存储,这意味着使用一个特殊对象,该对象将维护每个应用程序线程的独立对象。Python 通过threading.local()构造提供了这一功能。scoped_session
对象默认使用此对象作为存储,以便在调用scoped_session
注册表的所有调用者中维护单个Session
,但仅在单个线程的范围内。在不同线程中调用注册表的调用者将获得一个针对该其他线程本地的Session
实例。
使用这种技术,scoped_session
提供了一种快速而相对简单(如果熟悉线程本地存储的话)的方式,在应用程序中提供一个可以安全地从多个线程调用的单一全局对象。
与往常一样,scoped_session.remove()
方法会删除当前与线程关联的Session
(如果有的话)。然而,threading.local()
对象的一个优点是,如果应用程序线程本身结束,那么该线程的“存储”也会被垃圾回收。因此,在应用程序生成和销毁线程的情况下,使用线程本地作用域实际上是“安全”的,而无需调用scoped_session.remove()
。然而,事务本身的范围,即通过Session.commit()
或Session.rollback()
结束它们,通常仍然是必须在适当时候显式安排的,除非应用程序实际上将线程的寿命与事务的寿命绑定在一起。
在 Web 应用程序中使用线程本地作用域
如在何时构建会话、何时提交以及何时关闭会话?一节中所讨论的,Web 应用程序的架构围绕着web 请求的概念展开,而将这样的应用程序与Session
集成通常意味着Session
将与该请求相关联。事实证明,大多数 Python Web 框架(Twisted 和 Tornado 等异步框架是显著的例外)都以简单的方式使用线程,这样一个特定的 web 请求就在一个工作线程的范围内接收、处理和完成。当请求结束时,工作线程被释放到一个工作线程池中,在那里它可以处理另一个请求。
Web 请求与线程的这种简单对应关系意味着将Session
与线程关联也意味着它也与在该线程中运行的 web 请求相关联,反之亦然,前提是Session
仅在 Web 请求开始后创建,并在 Web 请求结束前销毁。因此,将scoped_session
作为将Session
与 Web 应用程序集成的一种快速方法是一种常见做法。下面的时序图说明了这个流程:
Web Server Web Framework SQLAlchemy ORM Code -------------- -------------- ------------------------------ startup -> Web framework # Session registry is established initializes Session = scoped_session(sessionmaker()) incoming web request -> web request -> # The registry is *optionally* starts # called upon explicitly to create # a Session local to the thread and/or request Session() # the Session registry can otherwise # be used at any time, creating the # request-local Session() if not present, # or returning the existing one Session.execute(select(MyClass)) # ... Session.add(some_object) # ... # if data was modified, commit the # transaction Session.commit() web request ends -> # the registry is instructed to # remove the Session Session.remove() sends output <- outgoing web <- response
使用上述流程,将 Session
与 Web 应用程序集成的过程具有确切的两个要求:
- 当 Web 应用程序首次启动时创建单个
scoped_session
注册表,确保此对象可被应用程序的其余部分访问。 - 确保在 Web 请求结束时调用
scoped_session.remove()
,通常通过与 Web 框架的事件系统集成以建立“请求结束时”事件来实现。
如前所述,上述模式仅是将 Session
与 Web 框架集成的一种潜在方式,特别是假设Web 框架将 Web 请求与应用程序线程关联。但是,强烈建议如果有的话,使用 Web 框架本身提供的集成工具,而不是 scoped_session
。
特别地,虽然使用线程本地可能很方便,但最好将 Session
与请求直接关联,而不是与当前线程关联。下一节关于自定义作用域详细介绍了一种更高级的配置,可以将 scoped_session
的使用与直接基于请求的作用域或任何类型的作用域相结合。
使用自定义创建的作用域
scoped_session
对象的“线程本地”作用域是“对 Session
进行作用域”多种选项之一。可以基于任何现有的获取“我们正在处理的当前事物”的系统定义自定义作用域。
假设一个 Web 框架定义了一个名为 get_current_request()
的库函数。使用该框架构建的应用程序可以随时调用此函数,其结果将是表示正在处理的当前请求的某种 Request
对象。如果 Request
对象是可散列的,那么此函数可以很容易地与 scoped_session
集成以将 Session
与请求关联起来。下面我们结合 Web 框架提供的假设事件标记 on_request_end
来说明这一点,该事件标记允许在请求结束时调用代码:
from my_web_framework import get_current_request, on_request_end from sqlalchemy.orm import scoped_session, sessionmaker Session = scoped_session(sessionmaker(bind=some_engine), scopefunc=get_current_request) @on_request_end def remove_session(req): Session.remove()
在上面的例子中,我们以通常的方式实例化 scoped_session
,唯一不同的是我们将我们的请求返回函数作为“scopefunc”传递。这指示 scoped_session
使用此函数生成字典键,每当注册表被调用以返回当前 Session
时。在这种情况下,确保实现可靠的“移除”系统非常重要,因为否则这个字典不会自我管理。
SqlAlchemy 2.0 中文文档(二十四)(5)https://developer.aliyun.com/article/1560560