添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议 》和 《 阿里云开发者社区知识产权保护指引 》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单 进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

参见上下文/线程本地会话教程。

在使用异步 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 )

将一个对象放入此 Session

代表 scoped_session 类的 Session 类的代理。

当通过 Session.add() 方法传递的对象处于瞬态状态时,它们将移动到挂起状态,直到下一次刷新,然后它们将移动到持久状态。

当通过 Session.add() 方法传递的对象处于分离状态时,它们将直接移动到持久状态。

如果 Session 使用的事务被回滚,则在它们被传递给 Session.add() 时处于瞬态的对象将被移回瞬态状态,并且将不再存在于此 Session 中。

Session.add_all()

添加新项目或现有项目 - 在使用会话基础知识中

如果尚未开始事务,则在此 Session 上开始事务或嵌套事务。

代表 scoped_session 类的 Session 类的代理。

Session 对象具有 自动开始 行为,因此通常不需要显式调用 Session.begin() 方法。但是,它可以用于控制事务状态开始的范围。

当用于开始最外层事务时,如果此 Session 已在事务内部,则会引发错误。

嵌套 - 如果为 True,则开始 SAVEPOINT 事务,并等效于调用 Session.begin_nested() 。有关 SAVEPOINT 事务的文档,请参阅使用 SAVEPOINT。

SessionTransaction 对象。请注意, SessionTransaction 充当 Python 上下文管理器,允许在“with”块中使用 Session.begin() 。请参阅显式开始获取示例。

Session.begin_nested()

在此 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 版本) 部分。

代理 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()

    代理 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()

    代理了 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()

    关闭此 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

    刷新待处理更改并提交当前事务。

    代理了 scoped_session 类的 Session 类。

    当 COMMIT 操作完成时,所有对象都被完全过期,擦除其内部内容,在下次访问对象时会自动重新加载。在此期间,这些对象处于过期状态,如果从 Session 中分离,它们将无法运行。此外,在使用基于 asyncio 的 API 时不支持此重新加载操作。 Session.expire_on_commit 参数可用于禁用此行为。

    Session 没有正在进行的事务时,表示自上次调用 Session.commit() 以来没有对此 Session 进行任何操作,则该方法将开始并提交一个仅限内部的“逻辑”事务,通常不会影响数据库,除非检测到待处理的刷新更改,但仍将调用事件处理程序和对象过期规则。

    最外层数据库事务会无条件提交,自动释放任何正在进行的 SAVEPOINT。

    管理事务。

    在使用 AsyncSession 时避免隐式 IO。

    返回一个对应于此 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
  • 将实例标记为已删除。

    代表 scoped_session 类为 Session 类代理。

    当传递的对象被假定为持久的或分离的时,调用该方法后,对象将保持在持久状态,直到下一次刷新进行。在此期间,该对象还将成为 Session.deleted 集合的成员。

    下一次刷新进行时,对象将转移到删除状态,表示在当前事务中为其行发出了 DELETE 语句。当事务成功提交时,已删除的对象将转移到分离状态,并且不再存在于此 Session 中。

    删除 - 在使用会话的基础知识

    实例在被修改但未被删除时被视为脏。

    请注意,这个“脏”计算是“乐观”的;大多数属性设置或集合修改操作都会将实例标记为“脏”,并将其放入这个集合中,即使属性的值没有净变化。在刷新时,将每个属性的值与其先前保存的值进行比较,如果没有净变化,则不会发生  SQL 操作(这是一项更昂贵的操作,因此只在刷新时执行)。

    要检查实例是否对其属性有可操作的净变化,请使用 Session.is_modified() 方法。

    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 对象。

    将实例的属性过期。

    代表 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()

    使此会话中的所有持久实例过期。

    代表 scoped_session 类,为 Session 类提供代理。

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

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

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

    刷新 / 过期 - 入门材料

    Session.expire()

    Session.refresh()

    Query.populate_existing()

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

    代表 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
    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”,调用看起来像:
  • 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

    返回此Session绑定的“bind”。

    代理为Session类,代表scoped_session类。

    “bind”通常是 Engine 的实例,除非 Session 已经被明确地直接绑定到 Connection 的情况除外。

    对于多重绑定或未绑定的 Session,使用 mapperclause 参数来确定要返回的适当绑定。

    注意,当通过 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

    如果此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()

    如果给定实例具有本地修改的属性,则返回True

    代理scoped_session类为Session类。

    此方法检索实例上每个受检的属性的历史记录,并将当前值与其先前提交的值进行比较(如果有)。

    这实际上是对在Session.dirty集合中检查给定实例的更昂贵且准确的版本;会执行每个属性净“脏”状态的完整测试。

    此方法有一些注意事项适用:

  • Session.dirty集合中存在的实例在使用此方法进行测试时可能报告False。这是因为对象可能已经通过属性变异接收到更改事件,从而将其放置在Session.dirty中,但最终状态与从数据库加载的状态相同,在此处没有净变化。
  • 当应用新值时,如果标量属性未加载或已过期,则可能未记录先前设置的值  - 在这些情况下,即使最终对其数据库值没有净变化,也假定属性已更改。大多数情况下,SQLAlchemy  在设置事件发生时不需要“旧”值,因此如果旧值不存在,则会跳过 SQL  调用的开销,这基于以下假设:标量值通常需要更新,在那些几种情况中不需要,平均而言比发出防御性 SELECT 要便宜。
    只有在属性容器的active_history标志设置为True时,才会无条件地在设置时获取“旧”值。通常为主键属性和不是简单多对一的标量对象引用设置此标志。要为任意映射列设置此标志,请使用带有column_property()active_history参数。
  • instance – 要测试的映射实例的待处理更改。
  • include_collections – 表示是否应该包含多值集合在操作中。将其设置为False是一种仅检测基于本地列的属性(即标量列或多对一外键)的方法,这些属性在刷新时会导致此实例的更新。
  • 将给定实例的状态复制到此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中的替代方法

    返回与此Session对应的新Query对象。

    代表scoped_session类的Session类的代理。

    注意Query对象在 SQLAlchemy 2.0 中已被废弃;现在使用select()构造 ORM 查询。

    SQLAlchemy 统一教程

    ORM 查询指南

    旧版查询 API - 旧版 API 文档

    返回一个类属性,当调用时会针对该类和当前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()

    对给定实例的过期和刷新属性。

    代理为 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 查询按照正常加载的方式刷新对象。

    结束此 Session 使用的事务资源和 ORM 对象,将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会将会…

    代理Session类,代表scoped_session类。

    此方法提供了与Session.close()方法历史上提供的相同的“仅重置”行为,其中Session的状态被重置,就像对象是全新的,准备好再次使用一样。然后,此方法可能对将Session.close_resets_only设置为FalseSession对象有用,以便“仅重置”行为仍然可用。

    新版本 2.0.22 中的内容。

    关闭 - 关于Session.close()Session.reset()语义的详细信息。

    Session.close() - 当参数Session.close_resets_only设置为False时,类似的方法还会阻止对会话的重新使用。

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

    代理Session类,代表scoped_session类。

    使用和参数与 Session.execute() 相同;返回结果是一个过滤对象 ScalarResult,该对象将返回单个元素而不是 Row 对象。

    一个 ScalarResult 对象

    新特性在版本 1.4.24 中添加:增加了 Session.scalars()

    新特性在版本 1.4.26 中添加:增加了scoped_session.scalars()

    选择 ORM 实体 - 将Session.execute()的行为与Session.scalars()进行对比

    一个可以基于“作用域”函数存储一个或多个单个类实例的注册表。

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

  • createfunc – 一个可调用的函数,返回要放置在注册表中的新对象
  • scopefunc – 一个可调用的函数,它将返回一个用于存储/检索对象的键。
  • init(), clear(), has(), set()

    sqlalchemy.util.ScopedRegistry (typing.Generic)

    上述代码完成了与通过调用注册表获取当前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