上下文/线程本地会话


回想一下 何时构造 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_sessionSession 的一个实例,我们现在可以使用它与数据库通信。这个相同的 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())


上面的代码完成的任务与获取电流 Session,然后使用该 Session


线程局部范围


熟悉多线程编程的用户会注意到,将任何内容表示为全局变量通常是一个坏主意,因为这意味着全局对象将由多个线程并发访问。会议 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 应用程序集成的过程恰好有两个要求:


  1. 在 Web 应用程序首次启动时创建一个 scoped_session 注册表,确保应用程序的其余部分可以访问此对象。


  2. 确保在 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_sessionSession 与请求相关联。 下面我们说明一下 这与 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


对象名称

描述


QueryPropertyDescriptor 查询属性描述符


描述应用于类级别的类型 scoped_session.query_property() 属性。

scoped_session


提供 Session 对象的范围管理。


ScopedRegistry 注册表


一个 Registry 可以基于“范围”函数存储单个类的一个或多个实例。


ThreadLocalRegistry (线程本地注册表)


使用 threading.local()ScopedRegistry 变量进行存储。


sqlalchemy.orm 中。scoped_session


提供 Session 对象的范围管理。


有关教程,请参阅 Contextual/Thread-local Sessions


注意


当使用异步 I/O (asyncio) 时,async-compatible 应使用 async_scoped_session 类来代替 scoped_session


类签名


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” 范围,并将使用 一个 Python threading.local() 来维护当前的 会话。 如果传递,该函数应返回 一个可哈希的代币;此令牌将用作 dictionary 来存储和检索当前的 会话


method sqlalchemy.orm.scoped_session. addinstance 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_allinstances Iterable[object] None


将给定的实例集合添加到此 Session


代表 Session 类代理 scoped_session 类。


有关一般行为描述,请参阅 Session.add() 的文档。


属性 sqlalchemy.orm.scoped_session. 自动刷新


代表 scoped_session 类的 Session.autoflush 属性的代理。


方法 sqlalchemy.orm.scoped_session. beginnested 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


另请参阅


使用 SAVEPOINT


可序列化隔离 / 保存点 / 事务性 DDL - 需要特殊解决方法 使用 SQLite 驱动程序,以便 SAVEPOINT 工作 正确。有关 asyncio 使用案例,请参阅 可序列化隔离 / 保存点 / 事务性 DDL (asyncio 版本)。


属性 sqlalchemy.orm.scoped_session. 绑定


代表 scoped_session 类的 Session.bind 属性的代理。


方法 sqlalchemy.orm.scoped_session. bulk_insert_mappingsmapper Mapper[Any]mappings Iterable[Dict[str Any]], return_defaults: bool = Falserender_nulls: bool = False


对给定的映射词典列表执行批量插入。


代表 Session 类代理 scoped_session 类。


旧版功能


此方法是 SQLAlchemy 2.0 系列的遗留功能。有关现代批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句按主键的 ORM 批量更新。2.0 API 与此方法共享实现细节,并添加了新功能。


参数

  • mapper—— 一个映射的类,或者实际的 Mapper 对象 表示映射中表示的单一对象 列表。


  • 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 值将被显式发送。必须注意确保不需要为整个作调用服务器端默认函数。


method sqlalchemy.orm.scoped_session. bulk_save_objectsobjects Iterable[object]return_defaults: bool = Falseupdate_changed_仅 bool = Truepreserve_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_mappingsmapper Mapper[Any]mappings Iterable[Dict[str Any]]


对给定的映射词典列表执行批量更新。


代表 Session 类代理 scoped_session 类。


旧版功能


此方法是 SQLAlchemy 2.0 系列的遗留功能。有关现代批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句按主键的 ORM 批量更新。2.0 API 与此方法共享实现细节,并添加了新功能。


参数

  • mapper—— 一个映射的类,或者实际的 Mapper 对象 表示映射中表示的单一对象 列表。


  • mappings—— 一系列字典,每个字典都包含要更新的映射行的状态,根据 mapped 类上的属性名称。如果映射引用多个表,例如联接继承映射,则每个字典可能包含所有表对应的键。所有存在但不属于主键的键都应用于 UPDATE 语句的 SET 子句;主键值是必需的,应用于 WHERE 子句。


方法 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。


method sqlalchemy.orm.scoped_session. configure**kwargs Any None


重新配置此 scoped_session


请参阅 sessionmaker.configure()。


method sqlalchemy.orm.scoped_session. connectionbind_arguments:_BindArgumentsNone=None, execution_options:CoreExecuteOptionsParameterNone=None 连接


返回与此对应的 Connection 对象 Session 对象的事务状态。


代表 Session 类代理 scoped_session 类。


返回与当前事务对应的 Connection,或者如果没有事务正在进行,则开始一个新的事务,并将 Connection 返回(请注意,没有 事务状态是使用 DBAPI 建立的,直到第一个 SQL 语句)。


多绑定或未绑定 Session 对象中的歧义可以通过任何可选的关键字参数来解决。这最终使用 get_bind() 方法进行解析。


参数

method sqlalchemy.orm.scoped_session. deleteinstance 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() 方法。


method sqlalchemy.orm.scoped_session. executestatement 可执行文件, 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 对象。


method sqlalchemy.orm.scoped_session. expireinstance 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 语句的特定情况有意义。


参数

  • instance– 要刷新的实例。


  • attribute_names – 可选的字符串属性名称列表,指示要过期的属性子集。


方法 sqlalchemy.orm.scoped_session. expire_all


使此 Session 中的所有持久性实例过期。


代表 Session 类代理 scoped_session 类。


下次访问持久化实例上的任何属性时, 将使用 Session 对象的当前事务上下文,以便加载给定实例的所有过期属性。请注意,高度隔离的事务将返回与之前在同一事务中读取的值相同的值,而不管该事务之外的数据库状态如何变化。


要使单个对象和这些对象上的各个属性过期,请使用 Session.expire()。


Session 对象的默认行为是每当 Session.rollback()Session.commit() 方法,以便可以为新事务加载新状态。因此,假设事务是隔离的,通常不需要调用 Session.expire_all()


method sqlalchemy.orm.scoped_session. expungeinstance object None(无)¶


从此 Session 中删除实例


代表 Session 类代理 scoped_session 类。


这将释放对实例的所有内部引用。将根据 Expunge Cascade 规则应用 Cascading


方法 sqlalchemy.orm.scoped_session. expunge_all


从此 Session 中删除所有对象实例。


代表 Session 类代理 scoped_session 类。


这相当于对 this 中的所有对象调用 expunge(obj) 会话


method sqlalchemy.orm.scoped_session. flushobjects:Sequence[Any]None=None None


将所有对象更改刷新到数据库。


代表 Session 类代理 scoped_session 类。


将所有待处理的对象创建、删除和修改作为 INSERT、DELETE、UPDATE 等写出到数据库中。作由 Session 的工作单元依存关系求解器自动排序。


数据库作将在当前事务上下文中发出,并且不会影响事务的状态,除非发生错误,在这种情况下,整个事务都会回滚。您可以在事务中随心所欲地 flush() 将更改从 Python 移动到数据库的事务缓冲区。


参数


对象


自选;将 flush作限制为仅对给定集合中的元素进行作。


此功能适用于一组极其狭窄的用例,在这些用例中,可能需要在完全 flush() 发生之前对特定对象进行作。它不用于一般用途。


method sqlalchemy.orm.scoped_session. getentity _EntityBindKey[_O]ident _PKIdentityArgument*, options:Sequence[ORMOption]None=None, populate_existing bool = Falsewith_for_update ForUpdateParameter = None, identity_token:AnyNone=None, execution_optionsOrmExecuteOptionsParameter = {}, 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


参数

  • entity—— 一个映射的类或 Mapper,指示要加载的实体类型。


  • 识别


    表示主键的标量、元组或字典。对于复合(例如多列)主键,应传递 Tuples 或 Dictionary。


    对于单列主键,标量调用形式通常是最方便的。如果一行的主键是值 “5”,则调用如下所示:

    my_object = session.get(SomeClass, 5)


    元组形式包含主键值,通常位于 它们与映射的 桌子 Object 的主键列,或者如果 Mapper.primary_key配置参数的 Sequences 中使用该参数。例如,如果一行的主键由整数数字 “5, 10” 表示,则调用将如下所示:

    my_object = session.get(SomeClass, (5, 10))


    字典形式应包括与主键的每个元素对应的映射属性名称作为键。如果映射的类具有 attributes idversion_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_bindmapper:_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


对于多重绑定或未绑定的 Sessionmapperclause 参数用于确定要返回的适当 BIND。


请注意,当通过 ORM作(例如 Session.query())调用 Session.get_bind() 时,通常存在 “mapper” 参数,每个 单个 INSERT/UPDATE/DELETE作 Session.flush()、调用等。


解决顺序为:


  1. 如果存在 mapper given 和 Session.binds,则首先根据正在使用的 mapper 找到一个 bind,然后是正在使用的 Map 类,然后是 Map 类的__mro__中存在的任何基类,从更具体的超类到更通用的超类。


  2. if 子句给定且 Session.binds 存在,则根据 Session.binds 中存在的给定子句中找到的 Table 对象找到绑定。


  3. 如果存在 Session.binds,则返回该 Session.binds


  4. if 子句,尝试返回链接到最终与子句关联的 MetaData 的 bind。


  5. 如果给定 mapper,则尝试返回链接到 MetaData 的绑定,该 MetaData 最终与 Table 或 mapper 映射到的其他可选内容相关联。


  6. 找不到 bind,UnboundExecutionError 被提升。


请注意,可以在 Session 的用户定义子类上覆盖 Session.get_bind() 方法以提供任何类型的 的绑定解析方案。 请参阅以下示例 自定义垂直分区


参数

method sqlalchemy.orm.scoped_session. get_oneentity _EntityBindKey[_O]ident _PKIdentityArgument*, options:Sequence[ORMOption]None=None, populate_existing bool = Falsewith_for_update ForUpdateParameter = None, identity_token:AnyNone=None, execution_optionsOrmExecuteOptionsParameter = {}, 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_keyclass_: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 类。


在 1.4 版本发生变更: Session 不再立即开始新的事务,因此当 Session 首次实例化时,此属性将为 False。


“partial rollback” 状态通常表示 Session 的 flush 过程失败,并且 Session.rollback() 方法才能完全回滚事务。


如果此 Session 根本不在事务中,则 Session 将在首次使用时自动启动,因此在这种情况下,Session.is_active将返回 True。


否则,如果此 Session 在事务中, 并且该事务尚未在内部回滚,则 Session.is_active 也将返回 True。


方法 sqlalchemy.orm.scoped_session. is_modifiedinstance objectinclude_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()


参数

  • instance—— 要测试待处理更改的映射实例。


  • include_collections– 指示作中是否应包含多值集合。将此设置为 False 是一种仅检测基于局部列的属性(即标量列或多对一外键)的方法,这些属性在刷新时会导致此实例发生 UPDATE。


method sqlalchemy.orm.scoped_session. mergeinstance _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_sessioninstance object→SessionNone


返回对象所属的 Session


代表 Session 类代理 scoped_session 类。


这是 object_session() 的别名。


method sqlalchemy.orm.scoped_session. query*entities _ColumnsClauseArgument[Any]**kwargs Any Query[任意]


返回与此对应的新 Query 对象 会话


代表 Session 类代理 scoped_session 类。


请注意,Query 对象是 SQLAlchemy 2.0 的遗留对象;select() 结构现在用于构造 ORM 查询。


方法 sqlalchemy.orm.scoped_session. query_propertyquery_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 关键字参数调用。


放置在类上的查询属性的数量没有限制。


method sqlalchemy.orm.scoped_session. refreshinstance 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 参数。


另请参阅


刷新 / 过期 - 介绍性材料


会话.expire()


Session.expire_all()


Populate Existing (填充现有) - 允许任何 ORM 查询刷新对象,就像正常加载对象一样。


方法 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 设置为 FalseSession 对象可能很有用,因此“仅重置”行为仍然可用。


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. scalarstatement 可执行文件, params:_CoreSingleExecuteParamsNone=None, *execution_options: OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=无, **kw 任意 任意


执行语句并返回标量结果。


代表 Session 类代理 scoped_session 类。


用法和参数与 Session.execute()的返回结果为标量 Python 值。


方法 sqlalchemy.orm.scoped_session. scalarsstatement Executable, params:_CoreAnyExecuteParamsNone=None, *execution_options OrmExecuteOptionsParameter = {}, bind_arguments:_BindArgumentsNone=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() 的行为进行对比


属性 sqlalchemy.orm.scoped_session. session_factory:sessionMaker[_S]


提供给 __init__ 的session_factory存储在此属性中,以后可以访问。当需要新的非范围的 Session 时,这可能很有用。


sqlalchemy.util 中。ScopedRegistry(范围注册表)¶


一个 Registry 可以基于“范围”函数存储单个类的一个或多个实例。


该对象将 __call__ 实现为 “getter”,因此通过调用 myregistry() 将返回当前范围的包含对象。


参数

  • createfunc —— 返回要放置在注册表中的新对象的可调用对象


  • scopefunc—— 一个可调用对象,它将返回一个 key 来存储/检索一个对象。


类签名


sqlalchemy.util.ScopedRegistry 键入。通用


方法 sqlalchemy.util.ScopedRegistry. __init__createfunc Callable[[] _T]scopefunc Callable[[] 任意]


构造一个新的 ScopedRegistry


参数

  • createfunc– 一个创建函数,如果不存在,它将为当前范围生成一个新值。


  • scopefunc– 一个函数,返回一个代表当前范围的可哈希令牌(例如,当前线程标识符)。


方法 sqlalchemy.util.ScopedRegistry. clear


清除当前范围(如果有)。


方法 sqlalchemy.util.ScopedRegistry. has bool


如果对象存在于当前范围内,则返回 True。


method sqlalchemy.util.ScopedRegistry. setobj _T


设置当前范围的值。


sqlalchemy.util 中。ThreadLocalRegistry(线程本地注册表)¶


使用 threading.local()ScopedRegistry 变量进行存储。


sqlalchemy.orm 中。QueryPropertyDescriptor 属性描述符


描述应用于类级别的类型 scoped_session.query_property() 属性。


2.0.5 新版功能.


类签名


sqlalchemy.orm.QueryPropertyDescriptor typing_extensions.协议