上下文/线程本地会话¶
回想一下 何时构造 Session,何时提交它,何时关闭它?一节中,引入了“会话范围”的概念,强调 Web 应用程序以及将 Session
范围与 Web 请求的范围联系起来的实践。大多数现代 Web 框架都包含集成工具,以便可以自动管理 Session
的范围,并且应该在这些工具可用时使用它们。
SQLAlchemy 包含它自己的帮助程序对象,这有助于建立用户定义的 Session
范围。第三方集成系统也使用它来帮助构建其集成方案。
该对象是 scoped_session
对象,它表示一个
Session
对象的注册表。如果您不熟悉注册表模式,可以在 Patterns of Enterprise 中找到一个很好的介绍。
架构。
警告
默认情况下,scoped_session
注册表使用 Python
线程.local()
来跟踪 Session
实例。这不是
必须与所有应用程序服务器兼容,尤其是那些使用 Greenlet 或其他替代形式的并发控制的应用程序服务器,这在中高并发场景中使用时可能会导致争用条件(例如随机发生的故障)。请阅读 线程局部范围 和
下面的 Using Thread-Local Scope with Web Applications,以更全面地理解使用 threading.local()
跟踪 Session
对象的含义,并考虑在使用不基于传统线程的应用程序服务器时更明确的范围界定方法。
注意
scoped_session
对象是许多 SQLAlchemy 应用程序使用的非常流行且有用的对象。然而,重要的是要注意,它只提出了一种解决 Session
问题的方法
管理。 如果您不熟悉 SQLAlchemy,尤其是
术语 “thread-local variable” 对您来说似乎很陌生,我们建议
如果可能,您首先要熟悉现成的集成
Flask-SQLAlchemy 等系统
或 zope.sqlalchemy 的 Kubernetes Halchemy。
scoped_session
是通过调用它来构造的,并向其传递一个
factory,它可以创建新的 Session
对象。工厂只是在调用时产生新对象的东西,在 Session
的情况下,最常见的工厂是本节前面介绍的 sessionmaker
。下面我们说明这种用法:
>>> from sqlalchemy.orm import scoped_session
>>> from sqlalchemy.orm import sessionmaker
>>> session_factory = sessionmaker(bind=some_engine)
>>> Session = scoped_session(session_factory)
我们创建的 scoped_session
对象现在将调用
sessionMaker
:
>>> some_session = Session()
上面,some_session
是 Session
的一个实例,我们现在可以使用它与数据库通信。这个相同的 Session
也存在于我们创建的 scoped_session
注册表中。如果我们第二次调用注册表,我们会得到相同的Session
:
>>> some_other_session = Session()
>>> some_session is some_other_session
True
此模式允许应用程序的不同部分调用全局
scoped_session
,以便所有这些区域可以共享同一会话,而无需显式传递它。我们在注册表中建立的 Session
将保留,直到我们通过调用 scoped_session.remove()
明确告诉我们的注册表处理它:
>>> Session.remove()
scoped_session.remove()
方法首先在当前 Session
上调用 Session.close(
),其效果是先释放 Session
拥有的所有连接/事务资源,然后丢弃 Session
本身。 这里的 “释放” 意味着连接将返回到其连接池,并且任何事务状态都会回滚,最终使用底层 DBAPI 连接的 rollback()
方法。
此时,scoped_session
对象是 “空的”,并且会在再次调用时创建一个新的Session
。如下图所示,这与我们之前的 Session
不同:
>>> new_session = Session()
>>> new_session is some_session
False
以上一系列步骤简要说明了 “registry” 模式的概念。有了这个基本概念,我们可以讨论这个模式如何进行的一些细节。
隐式方法访问¶
scoped_session
的工作很简单;hold on a Session
(保留会话)
为所有要求它的人。 作为产生更透明访问的一种手段
Session
中,scoped_session
还包括代理行为,这意味着注册表本身可以像 Session
一样处理
径直;当在此对象上调用方法时,它们将被代理到由 Registry 维护的基础 Session
:
Session = scoped_session(some_factory)
# equivalent to:
#
# session = Session()
# print(session.scalars(select(MyClass)).all())
#
print(Session.scalars(select(MyClass)).all())
线程局部范围¶
熟悉多线程编程的用户会注意到,将任何内容表示为全局变量通常是一个坏主意,因为这意味着全局对象将由多个线程并发访问。会议
Object 完全设计为以非并发方式使用,在多线程方面,这意味着“一次只能在一个线程中”。所以我们上面的 scoped_session
用法示例,其中相同的 Session
object 在多个调用中维护,这表明某些进程需要
到位,以便跨多个线程的多个调用实际上不会得到
同一会话的句柄。 我们将这个概念称为线程本地存储
这意味着,使用一个特殊的对象来维护一个不同的对象
每个应用程序线程。 Python 通过
线程.local()
构建。 默认情况下,scoped_session
对象使用此对象作为存储,以便为调用 scoped_session
注册表的所有用户维护单个 Session
,但仅限于单个
线。 在不同线程中调用注册表的调用方将获得
Session
实例。
使用这种技术,scoped_session
提供了一种快速且相对简单的(如果熟悉线程本地存储)的方法,可以在应用程序中安全地从多个线程调用单个全局对象。
scoped_session.remove()
方法一如既往地删除当前的
与线程关联的会话
(如果有)。 但是,
threading.local()
对象,如果应用程序线程本身结束,则该线程的 “存储” 也会被垃圾回收。因此,实际上,在生成和关闭线程的应用程序中使用线程局部范围是“安全的”,而无需调用 scoped_session.remove()。
但是,事务本身的范围,即通过 Session.commit()
或
Session.rollback()
通常仍然必须在适当的时间明确安排,除非应用程序实际上将线程的生命周期与事务的生命周期相关联。
在 Web 应用程序中使用线程局部范围¶
正如 何时构造 Session、何时提交以及何时关闭 一节中所讨论的,Web 应用程序是围绕 Web 请求的概念构建的,将此类应用程序与 Session
集成通常意味着 Session
将与该请求相关联。 事实证明,大多数 Python Web 框架
但有明显的例外,例如异步框架 Twisted 和
Tornado,以简单的方式使用线程,以便接收到特定的 Web 请求,
在单个工作线程的范围内处理和完成。当请求结束时,worker 线程被释放到一个 worker 池中,在那里它可以处理另一个请求。
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 框架的事件系统集成来建立“on request end”事件。
如前所述,上述模式只是集成 Session
的一种潜在方法
使用 Web 框架,它特别做出重要的假设
Web 框架将 Web 请求与应用程序线程相关联。但是,强烈建议使用 Web 框架随附的集成工具
如果可用,则使用 its 而不是 scoped_session
。
特别是,虽然使用本地线程很方便,但最好将 Session
直接与请求关联,而不是与当前线程关联。下一节关于自定义范围详细介绍了一种更高级的配置,它可以将 scoped_session
的使用与基于直接请求的范围或任何类型的范围相结合。
使用自定义创建的作用域¶
scoped_session
对象的默认行为 “thread local” 范围只是有关如何 “范围” 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
。在这种情况下,我们确保实现可靠的 “remove” 系统尤为重要,因为此字典不是自我管理的。
上下文会话 API¶
对象名称 |
描述 |
---|---|
|
|
|
|
|
|
|
-
类 sqlalchemy.orm 中。scoped_session¶
提供Session
对象的范围管理。
有关教程,请参阅 Contextual/Thread-local Sessions 。
注意
当使用异步 I/O (asyncio) 时,async-compatible 应使用async_scoped_session
类来代替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、 信息、 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
(键入。通用
)-
方法sqlalchemy.orm.scoped_session.
__call__(**kw: Any)_S ¶
返回当前Session
,使用scoped_session.session_factory
if not present 创建它。
参数
kw – 关键字参数将传递给scoped_session.session_factory
callable,如果现有的会话
不存在。如果会话
存在 和 keyword 参数,InvalidRequestError
引发。
-
方法sqlalchemy.orm.scoped_session.
__init__(session_factory: sessionmaker[_S], scopefunc:Callable[[],Any]None=None)¶
构建新scoped_session
。
参数
session_factory¶ – 创建新Session
的工厂 实例。这通常(但不一定)是一个实例的 sessionmaker
。
scopefunc¶ —— 定义当前范围的可选函数。如果未通过,则 scoped_session
object 假定 “thread-local” 范围,并将使用 一个 Pythonthreading.local()
来维护当前的会话
。 如果传递,该函数应返回 一个可哈希的代币;此令牌将用作 dictionary 来存储和检索当前的会话
。
-
methodsqlalchemy.orm.scoped_session.
add(instance: object, _warn: bool = True)无 ¶
将对象放入此Session
中。
代表Session
类代理scoped_session
类。
在传递给Session.add()
方法将移动到 pending 状态,直到下一次 flush,此时它们将进入 persistent 状态。
在传递给Session.add()
方法将移动到持久化 state 直接。
如果Session
使用的事务回滚, 对象,这些对象在传递给Session.add()
将移回 transient 状态,并且将不再存在于此会话
。
-
方法sqlalchemy.orm.scoped_session.
add_all(instances: Iterable[object])None ¶
将给定的实例集合添加到此Session
。
代表Session
类代理scoped_session
类。
有关一般行为描述,请参阅Session.add()
的文档。
-
属性sqlalchemy.orm.scoped_session.
自动刷新¶
代表scoped_session
类的Session.autoflush
属性的代理。
-
方法sqlalchemy.orm.scoped_session.
begin(nested: bool = False)SessionTransaction ¶
在此Session
上开始事务或嵌套事务(如果尚未开始)。
代表Session
类代理scoped_session
类。Session
对象具有 autostart 行为、 因此,通常不需要调用会话.begin()
方法。但是,它可以用于控制 事务状态开始的时间范围。
当用于开始最外层的事务时,如果此Session
已经在事务内部,则会引发错误。
参数
nested¶ – 如果为 True,则开始 SAVEPOINT 事务,等效于调用Session.begin_nested()。
为 有关 SAVEPOINT 事务的文档,请参阅 使用 SAVEPOINT。
结果SessionTransaction
对象。 请注意,会话事务
充当 Python 上下文管理器,允许Session.begin()
用于 “with” 块。 有关示例,请参阅 Explicit Begin 。
-
方法sqlalchemy.orm.scoped_session.
begin_nested()SessionTransaction ¶
在此 Session 上开始一个 “嵌套” 事务,例如 SAVEPOINT。
代表Session
类代理scoped_session
类。
目标数据库和关联的驱动程序必须支持 SQL SAVEPOINT,此方法才能正常运行。
有关 SAVEPOINT 事务的文档,请参阅使用 SAVEPOINT。
结果SessionTransaction
对象。 请注意,SessionTransaction
充当上下文管理器,允许Session.begin_nested()
用于 “with” 块。有关使用示例,请参阅使用 SAVEPOINT。
另请参阅
可序列化隔离 / 保存点 / 事务性 DDL - 需要特殊解决方法 使用 SQLite 驱动程序,以便 SAVEPOINT 工作 正确。有关 asyncio 使用案例,请参阅 可序列化隔离 / 保存点 / 事务性 DDL (asyncio 版本)。
-
属性sqlalchemy.orm.scoped_session.
绑定¶
代表scoped_session
类的Session.bind
属性的代理。
-
方法sqlalchemy.orm.scoped_session.
bulk_insert_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]], return_defaults: bool = False, render_nulls: bool = False)无 ¶
对给定的映射词典列表执行批量插入。
代表Session
类代理scoped_session
类。
旧版功能
此方法是 SQLAlchemy 2.0 系列的遗留功能。有关现代批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句和 按主键的 ORM 批量更新。2.0 API 与此方法共享实现细节,并添加了新功能。
参数
mappings¶—— 一系列字典,每个字典都包含要插入的映射行的状态,根据 mapped 类上的属性名称。如果映射引用多个表,例如联接继承映射,则每个字典必须包含要填充到所有表中的所有键。return_defaults¶ –
当 True 时,INSERT 进程将被更改 以确保将获取新生成的主键值。 此参数的基本原理通常是启用 要批量插入的联接表继承映射。
注意
对于不支持 RETURNING 的后端,Session.bulk_insert_mappings.return_defaults
参数会显著降低性能,因为 INSERT 语句不能再进行批处理。 看 INSERT 语句的 “Insert Many Values” 行为 了解哪些后端受到影响的背景信息。render_nulls¶ –
当 True 时,值None
将导致 NULL 值包含在 INSERT 语句中,而不是从 INSERT 中省略该列。这允许所有被 INSERT 的行具有相同的列集,从而允许将完整的行集批处理到 DBAPI。通常,包含与前一行不同的 NULL 值组合的每个列集必须省略呈现的 INSERT 语句中的不同列系列,这意味着它必须作为单独的语句发出。通过传递此标志,可以保证整组行可批处理为一个批处理;但是,代价是将被跳过由省略的列调用的服务器端默认值,因此必须注意确保这些不是必需的。
警告
设置此标志后,服务器端默认 SQL 值将 不会为作为 NULL 插入的列调用 ;NULL 值将被显式发送。必须注意确保不需要为整个作调用服务器端默认函数。
-
methodsqlalchemy.orm.scoped_session.
bulk_save_objects(objects: Iterable[object], return_defaults: bool = False, update_changed_仅: bool = True, preserve_order: bool = True)无 ¶
对给定的对象列表执行批量保存。
代表Session
类代理scoped_session
类。
旧版功能
此方法是 SQLAlchemy 2.0 系列的遗留功能。有关现代批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句和 按主键的 ORM 批量更新。
对于现有 ORM 映射对象的常规 INSERT 和 UPDATE,首选标准工作单元数据管理模式,在 SQLAlchemy Unified Tutorial 中介绍,网址为 使用 ORM 进行数据作。SQLAlchemy 2.0 现在对具有现代方言的 INSERT 语句使用“插入许多值”行为,这解决了以前批量 INSERT 缓慢的问题。
参数
对象¶ –
映射的对象实例序列。映射的对象按原样保留,并且不与会议
之后。
对于每个对象,对象是作为 INSERT 还是 UPDATE 发送,取决于Session
使用的相同规则 在传统作中;如果对象具有InstanceState.key
属性集,则假定对象为 “detached” 并且 将导致 UPDATE。 否则,使用 INSERT。
在 UPDATE 的情况下,语句根据已更改的属性进行分组,因此将成为每个 SET 子句的主题。如果update_changed_only
为 False,则每个对象中存在的所有属性都将应用于 UPDATE 语句,这可能有助于将语句分组到更大的 executemany() 中,并且还将减少检查属性历史记录的开销。
return_defaults¶ – 当 True 时,将一次插入一个缺少生成默认值的值的行,即整数主键默认值和序列,以便主键值 可用。 特别是,这将允许 joined-inheritance 等多表映射,无需正确插入 提前提供主键值;然而Session.bulk_save_objects.return_defaults
大大 降低方法的整体性能增益。强烈建议使用标准Session.add_all()
方法。
update_changed_only¶– 当 True 时,UPDATE 语句根据每个状态中已记录更改的属性呈现。当 False 时,除主键属性外,存在的所有属性都将呈现到 SET 子句中。
preserve_order¶ – 当为 True 时,插入和更新的顺序与对象的给定顺序完全匹配。当 False 时,常见类型的对象将分为 inserts 和 updates,以允许更多的批处理机会。
-
方法sqlalchemy.orm.scoped_session.
bulk_update_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]])无 ¶
对给定的映射词典列表执行批量更新。
代表Session
类代理scoped_session
类。
旧版功能
此方法是 SQLAlchemy 2.0 系列的遗留功能。有关现代批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句和 按主键的 ORM 批量更新。2.0 API 与此方法共享实现细节,并添加了新功能。
-
方法sqlalchemy.orm.scoped_session.
close()None ¶
关闭此使用的事务资源和 ORM 对象会话
。
代表Session
类代理scoped_session
类。
这将清除与此关联的所有 ORM 对象Session
结束任何正在进行的事务,并且 释放此
会话
本身已从关联的Engine
对象。然后,该作会离开Session
处于可以再次使用的状态。
提示
在默认运行模式下,Session.close()
方法不会阻止 Session 再次被使用。Session
本身实际上并没有明显的 “closed” 状态;它仅仅意味着Session
将释放所有数据库连接和 ORM 对象。
设置Session.close_resets_only
参数 设置为False
将使close
成为 final,这意味着将禁止对会话执行任何进一步的作。
在 1.4 版本发生变更:Session.close()
方法不会立即创建新的SessionTransaction
对象;相反,只有当Session
再次用于数据库作时,才会创建新的SessionTransaction
。
另请参阅
结束语 - 有关语义的详细信息Session.close()
和Session.reset() 的 Session.reset()
来获取。Session.reset()
- 一个类似的方法,其行为类似于close()
替换为参数Session.close_resets_only
设置为True
。
-
类方法sqlalchemy.orm.scoped_session.
close_all()无 ¶
关闭内存中的所有会话。
代表Session
类代理scoped_session
类。
1.3 版后已移除:Session.close_all()
方法已弃用,并将在未来发行版中删除。请参阅close_all_sessions()。
-
方法sqlalchemy.orm.scoped_session.
commit()无 ¶
刷新待处理的更改并提交当前事务。
代表Session
类代理scoped_session
类。
当 COMMIT作完成后,所有对象都已完全 expired,擦除其内部内容,这些内容将在下次访问对象时自动重新加载。在此期间,这些对象处于过期状态,如果它们与Session
分离,则无法运行。此外,使用面向 asyncio 的 API 时,不支持此重新加载作。Session.expire_on_commit
参数可用于禁用此行为。
当Session
没有事务时,表示未在此Session
上调用任何作 自上次调用Session.commit()
以来,该方法将开始并提交一个仅限内部的“逻辑”事务,除非检测到待处理的刷新更改,否则该事务通常不会影响数据库,但仍将调用事件处理程序和对象过期规则。
最外层的数据库事务被无条件提交,自动释放任何有效的 SAVEPOINT。
-
methodsqlalchemy.orm.scoped_session.
configure(**kwargs: Any)None ¶
-
methodsqlalchemy.orm.scoped_session.
connection(bind_arguments:_BindArgumentsNone=None, execution_options:CoreExecuteOptionsParameterNone=None)连接 ¶
返回与此对应的Connection
对象Session
对象的事务状态。
代表Session
类代理scoped_session
类。
返回与当前事务对应的Connection
,或者如果没有事务正在进行,则开始一个新的事务,并将Connection
返回(请注意,没有 事务状态是使用 DBAPI 建立的,直到第一个 SQL 语句)。
多绑定或未绑定Session
对象中的歧义可以通过任何可选的关键字参数来解决。这最终使用get_bind()
方法进行解析。
参数
bind_arguments¶ —— 绑定参数字典。可能包括 “mapper”、“bind”、“clause” 和其他传递给Session.get_bind()
的自定义参数。execution_options¶ –
将传递给Connection.execution_options()
的执行选项字典,当 仅首先获得连接。如果Session
中已存在该连接,则会发出警告并忽略参数。
-
methodsqlalchemy.orm.scoped_session.
delete(instance: object)None(无 )¶
将实例标记为已删除。
代表Session
类代理scoped_session
类。
假定对象为 persistent 或 通过时分离;调用该方法后,对象将保持持久状态,直到下一次刷新继续。在此期间,该对象也将是Session.deleted
集合的成员。
当下一次刷新继续时,对象将移动到 deleted 状态,指示在当前事务中为其行发出DELETE
语句。当事务成功提交后,已删除的对象将移动到 detached 状态,并且不再存在于此Session
中。
-
已删除属性sqlalchemy.orm.scoped_session.
¶
此Session
中标记为 'deleted' 的所有实例的集合
代表Session
类代理scoped_session
类。
-
attribute dirty(脏sqlalchemy.orm.scoped_session.
属性)¶
被视为 dirty 的所有持久性实例的集合。
代表Session
类代理scoped_session
类。
例如:some_mapped_object in session.dirty
当实例被修改但未被删除时,它们被视为脏实例。
请注意,这种 “肮脏 ”的计算是 “乐观的”;大多数属性设置或集合修改作会将实例标记为 'dirty' 并将其放置在此集中,即使属性的值没有净变化。在 flush 时,将每个属性的值与其之前保存的值进行比较,如果没有净变化,则不会发生 SQL作(这是一个成本更高的作,因此仅在 flush 时完成)。
要检查实例是否对其属性进行了可作的净更改,请使用Session.is_modified()
方法。
-
methodsqlalchemy.orm.scoped_session.
execute(statement: 可执行文件, params:_CoreAnyExecuteParamsNone=None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=无, _parent_execute_state:AnyNone=无, _add_event:AnyNone=无)结果[任何] ¶
执行 SQL 表达式构造。
代表Session
类代理scoped_session
类。
返回一个Result
对象,该对象表示语句执行的结果。
例如:from sqlalchemy import select result = session.execute(select(User).where(User.id == 5))
Session.execute()
的 API 协定类似于Connection
的 2.0 样式版本Connection.execute()
的 API 协定。
在 1.4 版本发生变更:Session.execute()
方法是 现在是 ORM 语句执行的主要点,当使用 2.0 样式ORM 用法。
参数
statement¶– 一个可执行语句(即一个Executable
表达式,例如select()
)。
params¶– 包含绑定参数值的可选字典或字典列表。如果是单个字典,则执行单行;如果是字典列表,则将调用 “executeMany”。每个字典中的键必须与语句中存在的参数名称相对应。execution_options¶ –
可选的 Dictionary of execution options,将与语句 execution 关联。此字典可以提供Connection.execution_options()
接受的选项的子集,还可以提供仅在 ORM 上下文中理解的其他选项。
另请参阅
ORM 执行选项 - 特定于 ORM 的执行选项
bind_arguments¶ – 要确定的附加参数字典 绑定。 可能包括 “mapper”、“bind” 或其他自定义参数。 此字典的内容将传递给Session.get_bind()
方法。
结果Result
对象。
-
methodsqlalchemy.orm.scoped_session.
expire(instance: object, attribute_names:Iterable[str]None=None)None(无 )¶
使实例上的属性过期。
代表Session
类代理scoped_session
类。
将实例的属性标记为过期。当过期的 属性,则会向Session
对象的当前事务上下文,以便加载给定实例的所有过期属性。请注意,高度隔离的事务将返回与之前在同一事务中读取的值相同的值,而不管该事务之外的数据库状态如何变化。
要同时使Session
中的所有对象过期,请使用Session.expire_all()。
Session
对象的默认行为是每当Session.rollback()
或Session.commit()
方法,以便可以为新事务加载新状态。因此,调用Session.expire()
仅对当前事务中发出非 ORM SQL 语句的特定情况有意义。
-
方法sqlalchemy.orm.scoped_session.
expire_all()无 ¶
使此 Session 中的所有持久性实例过期。
代表Session
类代理scoped_session
类。
下次访问持久化实例上的任何属性时, 将使用Session
对象的当前事务上下文,以便加载给定实例的所有过期属性。请注意,高度隔离的事务将返回与之前在同一事务中读取的值相同的值,而不管该事务之外的数据库状态如何变化。
要使单个对象和这些对象上的各个属性过期,请使用Session.expire()。
Session
对象的默认行为是每当Session.rollback()
或Session.commit()
方法,以便可以为新事务加载新状态。因此,假设事务是隔离的,通常不需要调用Session.expire_all()
。
-
methodsqlalchemy.orm.scoped_session.
expunge(instance: object)None(无 )¶
从此Session
中删除实例。
代表Session
类代理scoped_session
类。
这将释放对实例的所有内部引用。将根据 Expunge Cascade 规则应用 Cascading。
-
方法sqlalchemy.orm.scoped_session.
expunge_all()无 ¶
从此Session
中删除所有对象实例。
代表Session
类代理scoped_session
类。
这相当于对 this 中的所有对象调用expunge(obj)
会话
。
-
methodsqlalchemy.orm.scoped_session.
flush(objects:Sequence[Any]None=None)None ¶
将所有对象更改刷新到数据库。
代表Session
类代理scoped_session
类。
将所有待处理的对象创建、删除和修改作为 INSERT、DELETE、UPDATE 等写出到数据库中。作由 Session 的工作单元依存关系求解器自动排序。
数据库作将在当前事务上下文中发出,并且不会影响事务的状态,除非发生错误,在这种情况下,整个事务都会回滚。您可以在事务中随心所欲地 flush() 将更改从 Python 移动到数据库的事务缓冲区。
参数
对象¶ –
自选;将 flush作限制为仅对给定集合中的元素进行作。
此功能适用于一组极其狭窄的用例,在这些用例中,可能需要在完全 flush() 发生之前对特定对象进行作。它不用于一般用途。
-
methodsqlalchemy.orm.scoped_session.
get(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options:Sequence[ORMOption]None=None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token:AnyNone=None, execution_options:OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=None)→_ONone¶
根据给定的主键标识符返回实例,如果未找到,则返回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
。
参数
识别¶ –
表示主键的标量、元组或字典。对于复合(例如多列)主键,应传递 Tuples 或 Dictionary。
对于单列主键,标量调用形式通常是最方便的。如果一行的主键是值 “5”,则调用如下所示:my_object = session.get(SomeClass, 5)
元组形式包含主键值,通常位于 它们与映射的桌子
Object 的主键列,或者如果Mapper.primary_key
配置参数的 Sequences 中使用该参数。例如,如果一行的主键由整数数字 “5, 10” 表示,则调用将如下所示:my_object = session.get(SomeClass, (5, 10))
字典形式应包括与主键的每个元素对应的映射属性名称作为键。如果映射的类具有 attributesid
,version_id
作为存储对象主键值的属性,则调用将如下所示:my_object = session.get(SomeClass, {"id": 5, "version_id": 10})
options¶– 可选的 loader 选项序列,如果发出一个选项,将应用于查询。
populate_existing¶– 使该方法无条件地发出 SQL 查询并使用新加载的数据刷新对象,无论该对象是否已经存在。
with_for_update¶ – 可选布尔值True
,表示 FOR UPDATE 应该使用,或者可以是包含标志的字典,以便 指示 SELECT 的更具体的 FOR UPDATE 标志集; flags 应与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
。
-
方法sqlalchemy.orm.scoped_session.
get_bind(mapper:_EntityBindKey[_O]None=None, *, clause:ClauseElementNone=None, bind:_SessionBindNone=None, _sa_skip_events:boolNone=None, _sa_skip_for_implicit_returning: bool = False, **kw: Any)→EngineConnection¶
返回此Session
绑定到的 “bind”。
代表Session
类代理scoped_session
类。
“bind” 通常是Engine
的一个实例,除非Session
已经显式地直接绑定到Connection
。
对于多重绑定或未绑定的Session
,mapper
或clause
参数用于确定要返回的适当 BIND。
请注意,当通过 ORM作(例如Session.query()
)调用Session.get_bind()
时,通常存在 “mapper” 参数,每个 单个 INSERT/UPDATE/DELETE作Session.flush()、
调用等。
解决顺序为:
如果存在 mapper given 和Session.binds
,则首先根据正在使用的 mapper 找到一个 bind,然后是正在使用的 Map 类,然后是 Map 类的__mro__
中存在的任何基类,从更具体的超类到更通用的超类。
if 子句给定且Session.binds
存在,则根据Session.binds
中存在的给定子句中找到的Table
对象找到绑定。
如果存在Session.binds,则返回该 Session.binds
。
if 子句,尝试返回链接到最终与子句关联的MetaData
的 bind。
如果给定 mapper,则尝试返回链接到MetaData
的绑定,该 MetaData 最终与Table
或 mapper 映射到的其他可选内容相关联。
找不到bind,UnboundExecutionError
被提升。
请注意,可以在Session
的用户定义子类上覆盖Session.get_bind()
方法以提供任何类型的 的绑定解析方案。 请参阅以下示例 自定义垂直分区。
-
methodsqlalchemy.orm.scoped_session.
get_one(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options:Sequence[ORMOption]None=None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token:AnyNone=None, execution_options:OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=None)_O ¶
根据给定的主键标识符只返回一个实例,如果未找到则引发异常。
代表Session
类代理scoped_session
类。
sqlalchemy.orm.exc.NoResultFound
如果查询未选择任何行,则引发。
有关参数的详细文档,请参阅方法Session.get()。
2.0.22 新版功能.
结果
对象实例。
另请参阅Session.get()
- 等效方法
如果未找到具有提供的主键的行,则返回None
-
类方法sqlalchemy.orm.scoped_session.
identity_key(class_:Type[Any]None=None, ident:AnyTuple[Any,...]=None, *, instance:AnyNone=None, row:Row[Any]RowMappingNone=None, identity_token:AnyNone=None)_IdentityKeyType[Any] ¶
返回身份密钥。
代表Session
类代理scoped_session
类。
这是identity_key()
的别名。
-
属性sqlalchemy.orm.scoped_session.
identity_map¶
代表scoped_session
类的Session.identity_map
属性的代理。
-
属性sqlalchemy.orm.scoped_session.
信息¶
用户可修改的字典。
代表Session
类代理scoped_session
类。
此字典的初始值可以使用info
参数添加到Session
构造函数中,或者sessionmaker
构造函数或工厂方法。这里的字典始终是这个Session
的本地字典,并且可以独立于所有其他Session
对象进行修改。
-
属性sqlalchemy.orm.scoped_session.
is_active¶
如果此Session
未处于 “partial rollback” 状态,则为 True。
代表Session
类代理scoped_session
类。
“partial rollback” 状态通常表示Session
的 flush 过程失败,并且Session.rollback()
方法才能完全回滚事务。
如果此Session
根本不在事务中,则Session
将在首次使用时自动启动,因此在这种情况下,Session.is_active
将返回 True。
否则,如果此Session
在事务中, 并且该事务尚未在内部回滚,则Session.is_active
也将返回 True。
-
方法sqlalchemy.orm.scoped_session.
is_modified(instance: object, include_collections: bool = True)bool ¶
如果给定实例具有本地修改的属性,则返回True
。
代表Session
类代理scoped_session
类。
此方法检索实例上每个分析属性的历史记录,并执行当前值与其先前刷新或提交的值(如果有)的比较。
它实际上是更昂贵和准确的 版本。Session.dirty
集合;对每个属性的 Net “dirty” 状态执行完整测试。
例如:return session.is_modified(someobject)
此方法需要注意以下几点:
使用此方法测试时,Session.dirty
集合中存在的实例可能会报告False
。这是因为该对象可能已经通过属性 mutation 接收了更改事件,因此将其放置在Session.dirty
中,但最终状态与从数据库加载的状态相同,因此这里没有净变化。
如果在接收新值时未加载或过期,则在应用新值时,标量属性可能未记录先前设置的值 - 在这些情况下,假定该属性发生了变化,即使最终没有针对其数据库值的净变化。在大多数情况下,SQLAlchemy 在发生 set 事件时不需要“旧”值,因此如果旧值不存在,它会跳过 SQL 调用的费用,基于通常需要标量值的 UPDATE 的假设,并且在不需要的少数情况下,平均比发出防御性 SELECT 便宜。
仅当属性容器的active_history
标志设置为True
时,才会在设置时无条件地获取 “old” 值。此标志通常用于主键属性和标量对象引用,它们不是简单的多对一。要为任何任意映射列设置此标志,请使用active_history
参数替换为column_property()
的
-
methodsqlalchemy.orm.scoped_session.
merge(instance: _O, *, load: bool = True, options:Sequence[ORMOption]None=None)_O ¶
将给定实例的状态复制到此Session
中的相应实例中。
代表Session
类代理scoped_session
类。Session.merge()
检查源实例的主键属性,并尝试将其与 session 中相同主键的实例进行协调。如果在本地找不到,它会尝试根据主键从数据库中加载对象,如果找不到,则创建一个新实例。然后,将源实例上每个属性的状态复制到目标实例。然后,该方法返回生成的目标实例;原始源实例保持不变,并且如果尚未与 Session 关联,则不与Session
关联。
如果关联使用cascade=“merge”
映射,则此作将级联到关联的实例。
有关合并的详细讨论,请参阅 合并。
参数
instance¶- 要合并的实例。
加载¶ –
Boolean,当 False 时,merge()
切换到“高性能”模式,这会导致它放弃发出历史事件以及所有数据库访问。此标志用于将对象图传输到Session
中 从二级缓存,或传输刚刚加载的对象 放入 worker 线程或进程拥有的Session
中,而无需重新查询数据库。load=False
用例添加了一个警告,即给定的 对象必须处于 “干净” 状态,即没有待处理的更改 to be flushed - 即使传入对象与任何会话
。这样,当 merge作填充本地属性并级联到相关对象和集合时,这些值可以按原样“标记”到目标对象上,而无需生成任何历史记录或属性事件,也无需将传入数据与任何可能未加载的现有相关对象或集合进行协调。从 load=False
生成的对象总是被生成为 “clean”,因此给定的对象也应该是 “clean” 的,否则这表明该方法被误用。
选项¶ –
可选的 loader 选项序列,当 merge作从数据库中加载对象的现有版本时,这些选项将应用于Session.get()
方法。
在 1.4.24 版本加入.
另请参阅make_transient_to_detached()
- 提供将单个对象 “合并” 到Session
中的替代方法
-
属性sqlalchemy.orm.scoped_session.
new¶
此Session
中标记为 'new' 的所有实例的集合。
代表Session
类代理scoped_session
类。
-
属性sqlalchemy.orm.scoped_session.
no_autoflush¶
返回禁用 autoflush 的上下文管理器。
代表Session
类代理scoped_session
类。
例如:with session.no_autoflush: some_object = SomeClass() session.add(some_object) # won't autoflush some_object.related_thing = session.query(SomeRelated).first()
在with:
块中继续的作不会受到查询访问时发生的刷新的影响。这在初始化涉及现有数据库查询的一系列对象时非常有用,其中未完成的对象不应被刷新。
-
类方法sqlalchemy.orm.scoped_session.
object_session(instance: object)→SessionNone¶
返回对象所属的Session
。
代表Session
类代理scoped_session
类。
这是object_session()
的别名。
-
methodsqlalchemy.orm.scoped_session.
query(*entities: _ColumnsClauseArgument[Any], **kwargs: Any)Query[任意] ¶ -
代表Session
类代理scoped_session
类。
请注意,Query
对象是 SQLAlchemy 2.0 的遗留对象;select()
结构现在用于构造 ORM 查询。
-
方法sqlalchemy.orm.scoped_session.
query_property(query_cls:Type[Query[_T]]None=None)QueryPropertyDescriptor ¶
返回一个生成旧版Query
对象和当前session
时调用。
旧版功能
该scoped_session.query_property()
访问器特定于遗留的Query
对象,不被视为 2.0 样式 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
callable。可调用对象将使用类的映射器作为位置参数和 session 关键字参数调用。
放置在类上的查询属性的数量没有限制。
-
methodsqlalchemy.orm.scoped_session.
refresh(instance: object, attribute_names:Iterable[str]None=None, with_for_update: ForUpdateParameter = None)无 ¶
Expire 和 refresh 给定实例上的属性。
代表Session
类代理scoped_session
类。
所选属性将首先过期,就像使用Session.expire()
;然后,将向数据库发出 SELECT 语句,以使用当前事务中可用的当前值刷新面向列的属性。
如果面向relationship()
的属性已经预先加载到对象上,它们也会立即加载,使用与最初加载它们相同的预先加载策略。
在 1.4 版本加入: -Session.refresh()
方法也可以刷新预先加载的属性。
如果在 attribute_names 中明确命名,则通常使用SELECT
(或 “LAZY”)加载器策略加载的面向relationship()
的属性也将加载 集合,使用立即
加载器策略。如果未在Session.refresh.attribute_names
中命名延迟加载的关系,则它们将保留为“延迟加载”属性,并且不会隐式刷新。
在 2.0.4 版本发生变更:Session.refresh()
方法现在将面向延迟加载的relationship()
进行刷新 属性Session.refresh.attribute_names
收集。
提示
虽然Session.refresh()
方法能够 刷新面向列和关系的属性时,其 主要关注点是刷新本地面向列的属性 在单个实例上。对于更多开放式 “刷新” 功能, 包括刷新 一次,同时对 RELATIONSHIP LOADER 具有显式控制权 策略,请使用 填充现有功能。
请注意,高度隔离的事务将返回与之前在同一事务中读取的值相同的值,而不管该事务之外的数据库状态如何变化。刷新属性通常仅在尚未访问数据库行的事务开始时才有意义。
参数
attribute_names¶ – 可选。字符串属性名称的可迭代集合,指示要刷新的属性子集。
with_for_update¶ – 可选布尔值True
,表示 FOR UPDATE 应该使用,或者可以是包含标志的字典,以便 指示 SELECT 的更具体的 FOR UPDATE 标志集; flags 应与Query.with_for_update()
.取代Session.refresh.lockmode
参数。
-
方法sqlalchemy.orm.scoped_session.
remove()None ¶
释放当前Session
(如果存在)。
这将首先在当前Session
上调用Session.close()
方法,从而释放任何仍在保留的现有事务/连接资源;特别是回滚事务。然后,该会话
将被丢弃。下次在同一范围内使用时,scoped_session
将生成一个新的Session
对象。
-
方法sqlalchemy.orm.scoped_session.
reset()None ¶
关闭此使用的事务资源和 ORM 对象Session
,将会话重置为其初始状态。
代表Session
类代理scoped_session
类。
此方法提供与Session.close()
方法历史上提供了Session
的状态被重置,就好像对象是全新的一样,并准备好再次使用。然后,此方法对于将Session.close_resets_only
设置为False
的Session
对象可能很有用,因此“仅重置”行为仍然可用。
2.0.22 新版功能.
另请参阅
结束语 - 有关语义的详细信息Session.close()
和Session.reset() 的 Session.reset()
来获取。Session.close()
- 类似的方法将额外 当参数Session.close_resets_only
设置为False
。
-
方法sqlalchemy.orm.scoped_session.
rollback(None ¶
回滚当前正在进行的事务。
代表Session
类代理scoped_session
类。
如果没有正在进行的事务,则此方法为直通。
该方法始终回滚最顶层的数据库事务,丢弃可能正在进行的任何嵌套事务。
-
方法sqlalchemy.orm.scoped_session.
scalar(statement: 可执行文件, params:_CoreSingleExecuteParamsNone=None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=无, **kw: 任意)任意 ¶
执行语句并返回标量结果。
代表Session
类代理scoped_session
类。
用法和参数与Session.execute()
的返回结果为标量 Python 值。
-
方法sqlalchemy.orm.scoped_session.
scalars(statement: Executable, params:_CoreAnyExecuteParamsNone=None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=None, **kw: Any)ScalarResult[Any] ¶
执行语句并将结果作为标量返回。
代表Session
类代理scoped_session
类。
用法和参数与Session.execute()
的返回结果是一个ScalarResult
过滤对象,它将返回单个元素而不是Row
对象。
结果
1.4.24 版本中的新功能: 添加了Session.scalars()
1.4.26 版本中的新功能: 添加了scoped_session.scalars()
另请参阅
选择 ORM 实体 - 将Session.execute()
的行为与Session.scalars()
的行为进行对比
-
属性sqlalchemy.orm.scoped_session.
session_factory:sessionMaker[_S]¶
提供给 __init__ 的session_factory存储在此属性中,以后可以访问。当需要新的非范围的 Session
时,这可能很有用。
-
-
类 sqlalchemy.util 中。ScopedRegistry(范围注册表)¶
一个 Registry 可以基于“范围”函数存储单个类的一个或多个实例。
该对象将__call__
实现为 “getter”,因此通过调用myregistry()
将返回当前范围的包含对象。
类签名
类sqlalchemy.util.ScopedRegistry
(键入。通用
)-
方法sqlalchemy.util.ScopedRegistry.
__init__(createfunc: Callable[[], _T], scopefunc: Callable[[], 任意])¶
构造一个新的ScopedRegistry
。
-
方法sqlalchemy.util.ScopedRegistry.
clear()无 ¶
清除当前范围(如果有)。
-
方法sqlalchemy.util.ScopedRegistry.
has()bool ¶
如果对象存在于当前范围内,则返回 True。
-
methodsqlalchemy.util.ScopedRegistry.
set(obj: _T)无 ¶
设置当前范围的值。
-
-
类 sqlalchemy.util 中。ThreadLocalRegistry(线程本地注册表)¶
使用threading.local()
的ScopedRegistry
变量进行存储。
-
类 sqlalchemy.orm 中。QueryPropertyDescriptor 属性描述符¶
描述应用于类级别的类型scoped_session.query_property()
属性。
2.0.5 新版功能.
类签名
类sqlalchemy.orm.QueryPropertyDescriptor
(typing_extensions.协议
)