SqlAlchemy 2.0 中文文档(二十五)

2024-06-26 14:56:58 浏览数 (1)

原文:docs.sqlalchemy.org/en/20/contents.html

使用事件跟踪查询、对象和会话更改

原文:docs.sqlalchemy.org/en/20/orm/session_events.html

SQLAlchemy 特色是一个广泛的事件监听系统,贯穿于核心和 ORM 中。在 ORM 中,有各种各样的事件监听器钩子,这些钩子在 ORM 事件的 API 级别有文档记录。这些事件的集合多年来已经增长,包括许多非常有用的新事件,以及一些曾经不那么相关的旧事件。本节将尝试介绍主要的事件钩子以及它们何时可能被使用。

执行事件

从版本 1.4 新增:现在Session提供了一个单一全面的钩子,用于拦截 ORM 代表进行的所有 SELECT 语句,以及大量的 UPDATE 和 DELETE 语句。这个钩子取代了以前的QueryEvents.before_compile()事件以及QueryEvents.before_compile_update()QueryEvents.before_compile_delete()

Session提供了一个全面的系统,通过该系统,通过Session.execute()方法调用的所有查询,包括由Query发出的所有 SELECT 语句以及代表列和关系加载器发出的所有 SELECT 语句,都可以被拦截和修改。该系统使用SessionEvents.do_orm_execute()事件钩子以及ORMExecuteState对象来表示事件状态。

基本查询拦截

SessionEvents.do_orm_execute() 首先对查询的任何拦截都是有用的,包括由 Query 以 1.x 风格 发出的查询,以及当 ORM 启用的 2.0 风格 下传递给 Session.execute()select()update()delete() 构造。ORMExecuteState 构造提供了访问器,以允许修改语句、参数和选项:

代码语言:javascript复制
Session = sessionmaker(engine)

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if orm_execute_state.is_select:
        # add populate_existing for all SELECT statements

        orm_execute_state.update_execution_options(populate_existing=True)

        # check if the SELECT is against a certain entity and add an
        # ORDER BY if so
        col_descriptions = orm_execute_state.statement.column_descriptions

        if col_descriptions[0]["entity"] is MyEntity:
            orm_execute_state.statement = statement.order_by(MyEntity.name)

上述示例说明了对 SELECT 语句进行的一些简单修改。在这个层次上,SessionEvents.do_orm_execute() 事件钩子旨在取代之前使用的 QueryEvents.before_compile() 事件,该事件对各种加载器的各种类型并不一致地触发;此外,QueryEvents.before_compile() 仅适用于与 Query 的 1.x 风格 一起使用,而不适用于 2.0 风格 下使用 Session.execute()

添加全局的 WHERE / ON 条件

最常请求的查询扩展功能之一是向所有查询中的所有实体添加 WHERE 条件的能力。这可以通过使用 with_loader_criteria() 查询选项来实现,该选项可以单独使用,也可以在 SessionEvents.do_orm_execute() 事件中使用:

代码语言:javascript复制
from sqlalchemy.orm import with_loader_criteria

Session = sessionmaker(engine)

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if (
        orm_execute_state.is_select
        and not orm_execute_state.is_column_load
        and not orm_execute_state.is_relationship_load
    ):
        orm_execute_state.statement = orm_execute_state.statement.options(
            with_loader_criteria(MyEntity.public == True)
        )

在上述内容中,为所有 SELECT 语句添加了一个选项,该选项将限制针对MyEntity的所有查询以在public == True上进行过滤。该条件将应用于立即查询范围内该类的所有加载。with_loader_criteria()选项默认情况下还会自动传播到关系加载程序,这将应用于后续的关系加载,包括惰性加载,selectinloads 等。

对于一系列具有某些共同列结构的类,如果使用声明性混合来组合类,那么混合类本身可以与with_loader_criteria()选项结合使用,通过使用 Python lambda 来使用。 Python lambda 将针对与条件匹配的特定实体在查询编译时调用。假设一系列基于名为HasTimestamp的混合物的类:

代码语言:javascript复制
import datetime

class HasTimestamp:
    timestamp = mapped_column(DateTime, default=datetime.datetime.now)

class SomeEntity(HasTimestamp, Base):
    __tablename__ = "some_entity"
    id = mapped_column(Integer, primary_key=True)

class SomeOtherEntity(HasTimestamp, Base):
    __tablename__ = "some_entity"
    id = mapped_column(Integer, primary_key=True)

上述类SomeEntitySomeOtherEntity将分别具有一个timestamp列,其默认值为当前日期和时间。可以使用事件拦截所有扩展自HasTimestamp并过滤其timestamp列的对象,使其日期不晚于一个月前:

代码语言:javascript复制
@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if (
        orm_execute_state.is_select
        and not orm_execute_state.is_column_load
        and not orm_execute_state.is_relationship_load
    ):
        one_month_ago = datetime.datetime.today() - datetime.timedelta(months=1)

        orm_execute_state.statement = orm_execute_state.statement.options(
            with_loader_criteria(
                HasTimestamp,
                lambda cls: cls.timestamp >= one_month_ago,
                include_aliases=True,
            )
        )

警告

在调用with_loader_criteria()时使用 lambda 仅被调用一次每个唯一类。在此 lambda 内部不应调用自定义函数。请参阅使用 Lambda 将重要的速度增益添加到语句生成以获取“lambda SQL”功能的概述,该功能仅用于高级用途。

另请参阅

ORM 查询事件 - 包括上述with_loader_criteria()配方的工作示例。 ### 重新执行语句

深度炼金术

语句重新执行功能涉及稍微复杂的递归序列,并旨在解决将 SQL 语句的执行重新路由到各种非 SQL 上下文的相当困难的问题。下面链接的“狗窝缓存”和“水平分片”的双例应该用作指导,以确定何时适合使用此相当高级的功能。

ORMExecuteState能够控制给定语句的执行;这包括能力要么根本不调用语句,而是返回一个从缓存中检索到的预先构建的结果集,要么调用相同的语句多次,每次使用不同的状态,例如对多个数据库连接调用它,然后在内存中合并结果。这两种高级模式都在 SQLAlchemy 的示例套件中有详细说明。

SessionEvents.do_orm_execute()事件钩子内部时,可以使用ORMExecuteState.invoke_statement()方法来使用新的嵌套调用Session.execute()来调用语句,这将抢占当前正在进行的执行的后续处理,而是返回内部执行返回的Result。因此,在此过程中已调用的SessionEvents.do_orm_execute()钩子的事件处理程序也将在此嵌套调用中被跳过。

ORMExecuteState.invoke_statement()方法返回一个Result对象;然后该对象具有冻结为可缓存格式和解冻为新的Result对象的能力,以及将其数据与其他Result对象的数据合并的能力。

例如,使用SessionEvents.do_orm_execute()来实现缓存:

代码语言:javascript复制
from sqlalchemy.orm import loading

cache = {}

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if "my_cache_key" in orm_execute_state.execution_options:
        cache_key = orm_execute_state.execution_options["my_cache_key"]

        if cache_key in cache:
            frozen_result = cache[cache_key]
        else:
            frozen_result = orm_execute_state.invoke_statement().freeze()
            cache[cache_key] = frozen_result

        return loading.merge_frozen_result(
            orm_execute_state.session,
            orm_execute_state.statement,
            frozen_result,
            load=False,
        )

当上述钩子生效时,使用缓存的示例如下:

代码语言:javascript复制
stmt = (
    select(User).where(User.name == "sandy").execution_options(my_cache_key="key_sandy")
)

result = session.execute(stmt)

上面的例子中,自定义的执行选项被传递给Select.execution_options(),以建立一个“缓存键”,然后该键将被SessionEvents.do_orm_execute()钩子拦截。然后,这个缓存键将与可能存在于缓存中的FrozenResult对象进行匹配,并且如果存在,则重新使用该对象。该示例利用了Result.freeze()方法来“冻结”一个包含 ORM 结果的Result对象,以便它可以被存储在缓存中并多次使用。为了从“冻结”结果中返回一个活动结果,使用merge_frozen_result()函数将结果对象中的“冻结”数据合并到当前会话中。

上面的例子在 Dogpile 缓存中作为一个完整的例子实现。

ORMExecuteState.invoke_statement()方法也可以被多次调用,传递不同的信息给ORMExecuteState.invoke_statement.bind_arguments参数,以便Session每次都使用不同的Engine对象。这将每次返回一个不同的Result对象;这些结果可以使用Result.merge()方法合并在一起。这是水平分片扩展所采用的技术;请查看源代码以熟悉它。

另请参阅

Dogpile 缓存

水平分片 ## 持久化事件

可能是最广泛使用的一系列事件是“持久化”事件,它们对应于刷新过程。刷新是所有关于待处理对象更改的决定都会被做出,并以 INSERT、UPDATE 和 DELETE 语句的形式发送到数据库的地方。

before_flush()

SessionEvents.before_flush() 钩子是当应用程序希望在提交刷新时确保额外的持久性更改被执行时最常用的事件。 使用 SessionEvents.before_flush() 来验证对象的状态并在持久化之前组合其他对象和引用。在此事件中,可以安全地操纵会话的状态,即可以附加新对象,删除对象,并且可以自由更改对象上的单个属性,这些更改将在事件钩子完成时被纳入刷新过程中。

典型的 SessionEvents.before_flush() 钩子将被指示扫描集合 Session.newSession.dirtySession.deleted,以查找将要发生更改的对象。

有关 SessionEvents.before_flush() 的示例,请参见具有历史表的版本控制和使用时间行进行版本控制等示例。

after_flush()

SessionEvents.after_flush() 钩子在刷新过程的 SQL 被生成之后,但在被刷新的对象状态被更改之前调用。也就是说,您仍然可以检查 Session.newSession.dirtySession.deleted 集合,以查看刚刷新的内容,并且还可以使用像 AttributeState 这样的历史跟踪功能来查看刚刚持久化的更改。在 SessionEvents.after_flush() 事件中,可以根据观察到的更改向数据库发送额外的 SQL。

after_flush_postexec()

SessionEvents.after_flush_postexec()SessionEvents.after_flush() 之后不久调用,但是在对象状态已经被修改以考虑刚刚发生的刷新之后调用。Session.newSession.dirtySession.deleted 集合通常在此时完全为空。使用 SessionEvents.after_flush_postexec() 检查最终对象的标识映射,并可能发出附加的 SQL。在这个钩子中,有能力对对象进行新的更改,这意味着 Session 再次进入“脏”状态;Session 的机制会导致如果在此钩子中检测到新的更改,那么再次刷新如果在 Session.commit() 的上下文中调用了刷新;否则,待定更改将作为下一个正常刷新的一部分进行捆绑。当钩子在 Session.commit() 中检测到新的更改时,一个计数器确保在每次调用时,如果 SessionEvents.after_flush_postexec() 钩子持续添加新状态以刷新,则此方面的无限循环在 100 次迭代后停止。

映射器级刷新事件

除了刷新级别的钩子外,还有一套更精细的钩子,这些钩子更加细致,因为它们是基于每个对象调用的,并且根据刷新过程中的 INSERT、UPDATE 或 DELETE 进行分组。这些是映射器持久性钩子,它们也非常受欢迎,但是需要更加谨慎地对待这些事件,因为它们在已经进行的刷新过程的上下文中进行;在这里进行许多操作是不安全的。

这些事件是:

  • MapperEvents.before_insert()
  • MapperEvents.after_insert()
  • MapperEvents.before_update()
  • MapperEvents.after_update()
  • MapperEvents.before_delete()
  • MapperEvents.after_delete()

注意

需要注意的是,这些事件仅适用于会话刷新操作,而不适用于在 ORM-启用的 INSERT、UPDATE 和 DELETE 语句中描述的 ORM 级别的 INSERT/UPDATE/DELETE 功能。要拦截 ORM 级别的 DML,请使用SessionEvents.do_orm_execute()事件。

每个事件都会传递Mapper、映射对象本身以及用于发出 INSERT、UPDATE 或 DELETE 语句的Connection。这些事件的吸引力显而易见,因为如果应用程序想要将某些活动绑定到特定类型的对象在 INSERT 时被持久化的时间,钩子就非常具体;不像SessionEvents.before_flush()事件,不需要搜索诸如Session.new之类的集合以找到目标。然而,当调用这些事件时,表示完整列表的刷新计划,即将发出的每个单独的 INSERT、UPDATE、DELETE 语句已经已经决定,在这个阶段不允许进行任何更改。因此,甚至对于给定对象的其他属性也只能进行局部更改。对对象或其他对象的任何其他更改将影响Session的状态,这将导致其无法正常运行。

在这些映射器级持久性事件中不支持的操作包括:

  • Session.add()
  • Session.delete()
  • 映射集合追加、添加、移除、删除、丢弃等操作。
  • 映射关系属性设置/删除事件,即someobject.related = someotherobject

传递Connection的原因是鼓励在这里进行简单的 SQL 操作,直接在Connection上进行,例如在日志表中递增计数器或插入额外行。

也有许多每个对象操作根本不需要在刷新事件中处理。最常见的替代方法是在对象的__init__()方法中简单地建立额外的状态,例如创建要与新对象关联的其他对象。使用 Simple Validators 中描述的验证器是另一种方法;这些函数可以拦截属性的更改,并在响应属性更改时在目标对象上建立额外的状态更改。使用这两种方法,对象在到达刷新步骤之前就处于正确的状态。## 对象生命周期事件

事件的另一个用例是跟踪对象的生命周期。这指的是首次介绍于 Quickie Intro to Object States 的状态。

所有上述状态都可以完全通过事件进行跟踪。每个事件代表着一个独立的状态转换,意味着起始状态和目标状态都是被跟踪的一部分。除了初始的瞬态事件之外,所有事件都是以Session对象或类的形式出现的,这意味着它们可以与特定的Session对象关联:

代码语言:javascript复制
from sqlalchemy import event
from sqlalchemy.orm import Session

session = Session()

@event.listens_for(session, "transient_to_pending")
def object_is_pending(session, obj):
    print("new pending: %s" % obj)

或者使用Session类本身,以及特定的sessionmaker,这可能是最有用的形式:

代码语言:javascript复制
from sqlalchemy import event
from sqlalchemy.orm import sessionmaker

maker = sessionmaker()

@event.listens_for(maker, "transient_to_pending")
def object_is_pending(session, obj):
    print("new pending: %s" % obj)

监听器当然可以堆叠在一个函数上,这很可能是常见的情况。例如,要跟踪所有进入持久状态的对象:

代码语言:javascript复制
@event.listens_for(maker, "pending_to_persistent")
@event.listens_for(maker, "deleted_to_persistent")
@event.listens_for(maker, "detached_to_persistent")
@event.listens_for(maker, "loaded_as_persistent")
def detect_all_persistent(session, instance):
    print("object is now persistent: %s" % instance)
瞬态

所有映射对象在首次构建时都是瞬态的。在这种状态下,对象独立存在,不与任何Session关联。对于这种初始状态,没有特定的“转换”事件,因为没有Session,但是如果想要拦截任何瞬态对象被创建时,InstanceEvents.init()方法可能是最好的事件。此事件应用于特定类或超类。例如,要拦截特定声明基类的所有新对象:

代码语言:javascript复制
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import event

class Base(DeclarativeBase):
    pass

@event.listens_for(Base, "init", propagate=True)
def intercept_init(instance, args, kwargs):
    print("new transient: %s" % instance)
瞬态到待定

当瞬态对象首次通过Session.add()Session.add_all()方法与Session关联时,瞬态对象变为待定。对象也可能作为引用对象的“级联”结果成为Session的一部分,该引用对象是显式添加的。使用SessionEvents.transient_to_pending()事件检测瞬态到待定的转换过程:

代码语言:javascript复制
@event.listens_for(sessionmaker, "transient_to_pending")
def intercept_transient_to_pending(session, object_):
    print("transient to pending: %s" % object_)
待定到持久化

当一个刷新操作进行并且为实例执行 INSERT 语句时,待定对象变为持久化。该对象现在具有标识键。使用SessionEvents.pending_to_persistent()事件跟踪待定到持久化的过程:

代码语言:javascript复制
@event.listens_for(sessionmaker, "pending_to_persistent")
def intercept_pending_to_persistent(session, object_):
    print("pending to persistent: %s" % object_)
待定到瞬态

如果在待定对象被刷新之前调用Session.rollback()方法,或者在刷新对象之前调用Session.expunge()方法,则待定对象可以回退到瞬态状态。使用SessionEvents.pending_to_transient()事件跟踪待定到瞬态的过程:

代码语言:javascript复制
@event.listens_for(sessionmaker, "pending_to_transient")
def intercept_pending_to_transient(session, object_):
    print("transient to pending: %s" % object_)
作为持久化加载

当对象从数据库加载时,它们可以直接进入 Session 中的 persistent 状态。跟踪此状态转换等同于跟踪对象加载的方式,并且等同于使用 InstanceEvents.load() 实例级事件。但是,SessionEvents.loaded_as_persistent() 事件作为一个会话中心的钩子提供,用于拦截通过这种特定方式进入持久化状态的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "loaded_as_persistent")
def intercept_loaded_as_persistent(session, object_):
    print("object loaded into persistent state: %s" % object_)
持久化到瞬时

如果针对对象首次作为待处理对象添加的事务调用了 Session.rollback() 方法,持久化对象可以恢复到瞬时状态。在 ROLLBACK 的情况下,将该对象持久化的 INSERT 语句回滚,并将对象从 Session 中驱逐,使其再次成为瞬时状态。使用 SessionEvents.persistent_to_transient() 事件钩子跟踪从持久化恢复为瞬时的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_transient")
def intercept_persistent_to_transient(session, object_):
    print("persistent to transient: %s" % object_)
持久化到删除

当在 flush 过程中从数据库中删除了标记为删除的对象时,持久化对象进入 deleted 状态。请注意,这调用 Session.delete() 方法删除目标对象时并不相同Session.delete() 方法只是将对象标记为删除;直到 flush 进行之后才会发出实际的 DELETE 语句。在 flush 进行之后,目标对象的“deleted”状态才存在。

在“deleted”状态中,对象与 Session 仅有轻微关联。它既不在标识映射中,也不在指示其曾待删除的 Session.deleted 集合中。

从“deleted”状态,当事务提交时,对象可以进入分离状态,或者如果事务被回滚,则可以重新进入持久化状态。

使用 SessionEvents.persistent_to_deleted() 跟踪持久化到删除的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_deleted")
def intercept_persistent_to_deleted(session, object_):
    print("object was DELETEd, is now in deleted state: %s" % object_)
已删除到已分离

当会话的事务提交时,已删除对象将变为分离。在调用 Session.commit() 方法后,数据库事务已完成,Session 现在完全丢弃了已删除对象并删除了所有与其相关的关联。使用 SessionEvents.deleted_to_detached() 跟踪已删除到分离的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "deleted_to_detached")
def intercept_deleted_to_detached(session, object_):
    print("deleted to detached: %s" % object_)

注意

当对象处于已删除状态时,InstanceState.deleted 属性,可使用 inspect(object).deleted 访问,将返回 True。但是,当对象分离时,InstanceState.deleted 将再次返回 False。要检测对象是否已删除,无论它是否已分离,请使用 InstanceState.was_deleted 访问器。

持久到分离

当对象与 Session 解除关联时,通过 Session.expunge()Session.expunge_all()Session.close() 方法,持久对象将变为分离状态。

注意

如果一个对象的拥有者 Session 被应用程序解除引用并由于垃圾回收而被丢弃,该对象也可能会隐式分离。在这种情况下,不会发出任何事件

使用 SessionEvents.persistent_to_detached() 事件跟踪对象从持久状态转为分离状态:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_detached")
def intercept_persistent_to_detached(session, object_):
    print("object became detached: %s" % object_)
分离到持久

当分离对象使用 Session.add() 或等效方法重新关联到会话时,它将变为持久对象。跟踪对象从分离状态返回持久状态时使用 SessionEvents.detached_to_persistent() 事件:

代码语言:javascript复制
@event.listens_for(sessionmaker, "detached_to_persistent")
def intercept_detached_to_persistent(session, object_):
    print("object became persistent again: %s" % object_)
已删除到持久

当删除对象在其所在的事务被回滚时,可以将其恢复为持久状态,使用Session.rollback()方法回滚。使用SessionEvents.deleted_to_persistent()事件跟踪将删除的对象移回持久状态:

代码语言:javascript复制
@event.listens_for(sessionmaker, "deleted_to_persistent")
def intercept_deleted_to_persistent(session, object_):
    print("deleted to persistent: %s" % object_)
```## 事务事件

事务事件允许应用在`Session`级别上发生事务边界时收到通知,以及当`Session`更改`Connection`对象上的事务状态时。

    `SessionEvents.after_transaction_create()`,`SessionEvents.after_transaction_end()` - 这些事件跟踪`Session`的逻辑事务范围,不特定于单个数据库连接。这些事件旨在帮助集成事务跟踪系统,如`zope.sqlalchemy`。当应用程序需要将某些外部范围与`Session`的事务范围对齐时,请使用这些事件。这些挂钩反映了`Session`的“嵌套”事务行为,因为它们跟踪逻辑“子事务”以及“嵌套”(例如,SAVEPOINT)事务。

    `SessionEvents.before_commit()`、`SessionEvents.after_commit()`、`SessionEvents.after_begin()`、`SessionEvents.after_rollback()`、`SessionEvents.after_soft_rollback()` - 这些事件允许从数据库连接的角度跟踪事务事件。特别是`SessionEvents.after_begin()`是一个每个连接的事件;一个维护多个连接的`Session`将为每个连接在当前事务中使用时单独发出此事件。然后回滚和提交事件指的是 DBAPI 连接自身直接接收回滚或提交指令的时候。

## 属性更改事件

属性更改事件允许拦截对象上特定属性被修改的时机。这些事件包括`AttributeEvents.set()`、`AttributeEvents.append()`和`AttributeEvents.remove()`。这些事件非常有用,特别是对于每个对象的验证操作;然而,使用“验证器”钩子通常更加方便,它在幕后使用这些钩子;请参阅 Simple Validators 以了解背景信息。属性事件也是反向引用机制的基础。一个说明属性事件使用的示例在 Attribute Instrumentation 中。

## 执行事件

新版本 1.4 中新增:`Session`现在具有一个全面的钩子,旨在拦截所有代表 ORM 执行的 SELECT 语句以及批量 UPDATE 和 DELETE 语句。这个钩子取代了之前的`QueryEvents.before_compile()`事件以及`QueryEvents.before_compile_update()`和`QueryEvents.before_compile_delete()`。

`Session`具有一个全面的系统,通过该系统可以拦截和修改通过`Session.execute()`方法调用的所有查询,其中包括由`Query`发出的所有 SELECT 语句以及所有代表列和关系加载程序发出的 SELECT 语句。该系统利用了`SessionEvents.do_orm_execute()`事件钩子以及`ORMExecuteState`对象来表示事件状态。

### 基本查询拦截

`SessionEvents.do_orm_execute()`首先对查询的任何拦截都是有用的,这包括由`Query`发出的 1.x 风格以及当 ORM 启用的 2.0 风格的`select()`,`update()`或`delete()`构造被传递给`Session.execute()`时。`ORMExecuteState`构造提供了访问器,允许修改语句、参数和选项:

```py
Session = sessionmaker(engine)

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if orm_execute_state.is_select:
        # add populate_existing for all SELECT statements

        orm_execute_state.update_execution_options(populate_existing=True)

        # check if the SELECT is against a certain entity and add an
        # ORDER BY if so
        col_descriptions = orm_execute_state.statement.column_descriptions

        if col_descriptions[0]["entity"] is MyEntity:
            orm_execute_state.statement = statement.order_by(MyEntity.name)

上面的示例说明了对 SELECT 语句的一些简单修改。在这个级别上,SessionEvents.do_orm_execute() 事件钩子旨在替换以前对各种加载器不一致触发的 QueryEvents.before_compile() 事件的使用;此外,QueryEvents.before_compile() 仅适用于 1.x 样式 与 Query 一起使用,并不适用于 2.0 样式 与 Session.execute() 一起使用。

添加全局 WHERE / ON 条件

最常请求的查询扩展功能之一是能够向所有查询中的所有实体添加 WHERE 条件。通过使用 with_loader_criteria() 查询选项,可以实现此目的,该选项可以单独使用,或者最好在 SessionEvents.do_orm_execute() 事件中使用:

代码语言:javascript复制
from sqlalchemy.orm import with_loader_criteria

Session = sessionmaker(engine)

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if (
        orm_execute_state.is_select
        and not orm_execute_state.is_column_load
        and not orm_execute_state.is_relationship_load
    ):
        orm_execute_state.statement = orm_execute_state.statement.options(
            with_loader_criteria(MyEntity.public == True)
        )

上面,所有 SELECT 语句都添加了一个选项,将限制针对 MyEntity 的所有查询,以在 public == True 上进行过滤。这些条件将应用于立即查询范围内该类的所有加载。with_loader_criteria() 选项默认情况下也会自动传播到关系加载器,这将应用于后续的关系加载,包括延迟加载、selectinloads 等。

对于一系列具有某些共同列结构的类,如果这些类使用 declarative mixin 进行组合,那么 mixin 类本身可以与 with_loader_criteria() 选项结合使用,方法是使用 Python lambda。Python lambda 将在查询编译时针对符合条件的特定实体被调用。假设有一系列基于名为 HasTimestamp 的 mixin 的类:

代码语言:javascript复制
import datetime

class HasTimestamp:
    timestamp = mapped_column(DateTime, default=datetime.datetime.now)

class SomeEntity(HasTimestamp, Base):
    __tablename__ = "some_entity"
    id = mapped_column(Integer, primary_key=True)

class SomeOtherEntity(HasTimestamp, Base):
    __tablename__ = "some_entity"
    id = mapped_column(Integer, primary_key=True)

上述类 SomeEntitySomeOtherEntity 将分别具有一个默认为当前日期和时间的列 timestamp。可以使用事件拦截从 HasTimestamp 扩展的所有对象,并在一个月前之内的日期上过滤它们的 timestamp 列:

代码语言:javascript复制
@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if (
        orm_execute_state.is_select
        and not orm_execute_state.is_column_load
        and not orm_execute_state.is_relationship_load
    ):
        one_month_ago = datetime.datetime.today() - datetime.timedelta(months=1)

        orm_execute_state.statement = orm_execute_state.statement.options(
            with_loader_criteria(
                HasTimestamp,
                lambda cls: cls.timestamp >= one_month_ago,
                include_aliases=True,
            )
        )

警告

在调用with_loader_criteria()时使用 lambda 只会每个唯一类调用一次。在此 lambda 内部不应调用自定义函数。有关“lambda SQL”功能的概述,请参阅使用 Lambda 为语句生成带来显著速度提升,这仅适用于高级用法。

另请参阅

ORM 查询事件 - 包括上述with_loader_criteria()示例的工作示例。### 重新执行语句

深度炼金术

重新执行功能涉及稍微复杂的递归序列,并旨在解决能够将 SQL 语句的执行重新路由到各种非 SQL 上下文的相当困难的问题。下面链接的“狗窝缓存”和“水平分片”这两个示例应该作为指导,指出何时适合使用这个相当高级的功能。

ORMExecuteState能够控制给定语句的执行;这包括不执行语句的能力,允许从缓存中检索到的预构建结果集返回,以及多次以不同状态调用相同语句的能力,例如针对多个数据库连接调用它,然后在内存中合并结果。这两种高级模式在 SQLAlchemy 的示例套件中有详细展示。

当在SessionEvents.do_orm_execute()事件钩子内部时,可以使用ORMExecuteState.invoke_statement()方法来使用新的嵌套调用Session.execute()来调用语句,这将预先中断当前正在进行的执行的后续处理,而是返回内部执行返回的Result。在此过程中为SessionEvents.do_orm_execute()钩子调用的事件处理程序也将在此嵌套调用中被跳过。

ORMExecuteState.invoke_statement()方法返回一个Result对象;该对象具有将其“冻结”为可缓存格式并“解冻”为新的Result对象的能力,以及将其数据与其他Result对象的数据合并的能力。

例如,使用SessionEvents.do_orm_execute()来实现缓存:

代码语言:javascript复制
from sqlalchemy.orm import loading

cache = {}

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if "my_cache_key" in orm_execute_state.execution_options:
        cache_key = orm_execute_state.execution_options["my_cache_key"]

        if cache_key in cache:
            frozen_result = cache[cache_key]
        else:
            frozen_result = orm_execute_state.invoke_statement().freeze()
            cache[cache_key] = frozen_result

        return loading.merge_frozen_result(
            orm_execute_state.session,
            orm_execute_state.statement,
            frozen_result,
            load=False,
        )

有了上述钩子,使用缓存的示例如下:

代码语言:javascript复制
stmt = (
    select(User).where(User.name == "sandy").execution_options(my_cache_key="key_sandy")
)

result = session.execute(stmt)

以上,在Select.execution_options()中传递了一个自定义执行选项,以建立一个“缓存键”,然后会被SessionEvents.do_orm_execute()钩子拦截。这个缓存键然后会与可能存在于缓存中的FrozenResult对象匹配,如果存在,则会重新使用该对象。该示例利用了Result.freeze()方法来“冻结”一个Result对象,其中将包含 ORM 结果,以便将其存储在缓存中并多次使用。为了从“冻结”结果中返回一个实时结果,使用merge_frozen_result()函数将结果对象中的“冻结”数据合并到当前会话中。

上述示例在 Dogpile Caching 中作为一个完整示例实现。

ORMExecuteState.invoke_statement() 方法也可以被多次调用,传递不同的信息给 ORMExecuteState.invoke_statement.bind_arguments 参数,以便 Session 每次都使用不同的 Engine 对象。每次都会返回一个不同的 Result 对象;这些结果可以使用 Result.merge() 方法合并在一起。这是 水平分片 扩展所使用的技术;请查看源代码以熟悉。

另请参阅

Dogpile Caching

水平分片

基本查询拦截

SessionEvents.do_orm_execute() 首先适用于任何类型的查询拦截,包括由 Query 以 1.x 样式 发出的查询,以及当启用 ORM 的 2.0 样式 select()update()delete() 构造传递给 Session.execute() 时。 ORMExecuteState 构造提供了访问器,允许对语句、参数和选项进行修改:

代码语言:javascript复制
Session = sessionmaker(engine)

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if orm_execute_state.is_select:
        # add populate_existing for all SELECT statements

        orm_execute_state.update_execution_options(populate_existing=True)

        # check if the SELECT is against a certain entity and add an
        # ORDER BY if so
        col_descriptions = orm_execute_state.statement.column_descriptions

        if col_descriptions[0]["entity"] is MyEntity:
            orm_execute_state.statement = statement.order_by(MyEntity.name)

上述示例说明了对 SELECT 语句的一些简单修改。在此级别上,SessionEvents.do_orm_execute()事件挂钩旨在替换先前使用的QueryEvents.before_compile()事件,该事件对各种加载程序未始终触发;另外,QueryEvents.before_compile()仅适用于 1.x 样式与Query一起使用,而不适用于 2.0 样式使用Session.execute()

添加全局 WHERE / ON 条件

最常请求的查询扩展功能之一是能够向所有查询中的实体添加 WHERE 条件的能力。这可以通过使用with_loader_criteria()查询选项来实现,该选项可以单独使用,或者最好在SessionEvents.do_orm_execute()事件中使用:

代码语言:javascript复制
from sqlalchemy.orm import with_loader_criteria

Session = sessionmaker(engine)

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if (
        orm_execute_state.is_select
        and not orm_execute_state.is_column_load
        and not orm_execute_state.is_relationship_load
    ):
        orm_execute_state.statement = orm_execute_state.statement.options(
            with_loader_criteria(MyEntity.public == True)
        )

在上述示例中,一个选项被添加到所有 SELECT 语句中,该选项将限制所有针对MyEntity的查询以在public == True上进行过滤。这些条件将应用于立即查询范围内该类的所有加载。with_loader_criteria()选项默认情况下也会自动传播到关系加载程序,这将应用于后续的关系加载,包括惰性加载、selectinloads 等。

对于一系列具有一些共同列结构的类,如果使用声明性混合组合类,那么混合类本身可以与with_loader_criteria()选项一起使用,方法是使用 Python lambda。Python lambda 将在与条件匹配的特定实体的查询编译时间调用。假设有一系列基于名为HasTimestamp的混合类的类:

代码语言:javascript复制
import datetime

class HasTimestamp:
    timestamp = mapped_column(DateTime, default=datetime.datetime.now)

class SomeEntity(HasTimestamp, Base):
    __tablename__ = "some_entity"
    id = mapped_column(Integer, primary_key=True)

class SomeOtherEntity(HasTimestamp, Base):
    __tablename__ = "some_entity"
    id = mapped_column(Integer, primary_key=True)

上述类SomeEntitySomeOtherEntity将各自具有一个列timestamp,默认值为当前日期和时间。可以使用事件拦截所有从HasTimestamp扩展的对象,并将它们的timestamp列过滤为一个月前的日期:

代码语言:javascript复制
@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if (
        orm_execute_state.is_select
        and not orm_execute_state.is_column_load
        and not orm_execute_state.is_relationship_load
    ):
        one_month_ago = datetime.datetime.today() - datetime.timedelta(months=1)

        orm_execute_state.statement = orm_execute_state.statement.options(
            with_loader_criteria(
                HasTimestamp,
                lambda cls: cls.timestamp >= one_month_ago,
                include_aliases=True,
            )
        )

警告

在调用 with_loader_criteria() 时,使用 lambda 内部的调用每个唯一类仅调用一次。自定义函数不应在此 lambda 内部调用。请参阅 使用 Lambda 来为语句生成带来显著的速度提升 以获得“lambda SQL”功能的概述,该功能仅供高级使用。

另请参阅

ORM 查询事件 - 包括上述 with_loader_criteria() 配方的工作示例。

重新执行语句

深度炼金术

语句重新执行功能涉及稍微复杂的递归序列,并且旨在解决将 SQL 语句的执行重新路由到各种非 SQL 上下文的相当困难的问题。下面链接的“狗窝缓存”和“水平分片”两个示例应该用作指导,以确定何时使用此相当高级的功能。

ORMExecuteState 能够控制给定语句的执行;这包括不执行该语句的能力,允许从缓存中检索到的预构造结果集被返回,以及多次以不同状态调用相同语句的能力,例如对多个数据库连接执行它,然后在内存中合并结果。这两种高级模式都在下面详细介绍了 SQLAlchemy 的示例套件中进行了演示。

SessionEvents.do_orm_execute() 事件钩子内部时,可以使用 ORMExecuteState.invoke_statement() 方法来使用新的嵌套调用 Session.execute() 来调用语句,这将预先阻止当前正在进行的执行的后续处理,并返回内部执行的 Result。在此过程中对 SessionEvents.do_orm_execute() 钩子所调用的事件处理程序也将在此嵌套调用中被跳过。

ORMExecuteState.invoke_statement()方法返回一个Result对象;此对象具有将其“冻结”为可缓存格式并“解冻”为新的Result对象的能力,以及将其数据与其他Result对象的数据合并的能力。

例如,使用SessionEvents.do_orm_execute()实现缓存:

代码语言:javascript复制
from sqlalchemy.orm import loading

cache = {}

@event.listens_for(Session, "do_orm_execute")
def _do_orm_execute(orm_execute_state):
    if "my_cache_key" in orm_execute_state.execution_options:
        cache_key = orm_execute_state.execution_options["my_cache_key"]

        if cache_key in cache:
            frozen_result = cache[cache_key]
        else:
            frozen_result = orm_execute_state.invoke_statement().freeze()
            cache[cache_key] = frozen_result

        return loading.merge_frozen_result(
            orm_execute_state.session,
            orm_execute_state.statement,
            frozen_result,
            load=False,
        )

有了上述钩子,使用缓存的示例如下所示:

代码语言:javascript复制
stmt = (
    select(User).where(User.name == "sandy").execution_options(my_cache_key="key_sandy")
)

result = session.execute(stmt)

上面,在Select.execution_options()中传递了自定义执行选项,以建立一个“缓存键”,然后会被SessionEvents.do_orm_execute()钩子拦截。然后将该缓存键与可能存在于缓存中的FrozenResult对象进行匹配,如果存在,则重新使用该对象。该方案利用了Result.freeze()方法来“冻结”一个Result对象,其中包含上面的 ORM 结果,以便将其存储在缓存中并多次使用。为了从“冻结”的结果中返回实时结果,使用了merge_frozen_result()函数将结果对象中的“冻结”数据合并到当前会话中。

上述示例已作为一个完整示例在 Dogpile Caching 中实现。

ORMExecuteState.invoke_statement() 方法也可能被多次调用,传递不同的信息给 ORMExecuteState.invoke_statement.bind_arguments 参数,以便 Session 每次使用不同的 Engine 对象。这将每次返回一个不同的 Result 对象;这些结果可以使用 Result.merge() 方法合并在一起。这是水平分片扩展所采用的技术;请参阅源代码以熟悉。

另请参阅

Dogpile 缓存

水平分片

持久性事件

最广泛使用的系列事件可能是“持久性”事件,它们对应于刷新过程。 刷新是关于对对象的待定更改的所有决定都是在这里做出的,然后以 INSERT、UPDATE 和 DELETE 语句的形式发出到数据库。

before_flush()

SessionEvents.before_flush() 钩子是应用程序希望在提交时确保对数据库进行额外持久性更改时最常用的事件。使用 SessionEvents.before_flush() 来在对象上操作以验证它们的状态,以及在它们持久化之前组合额外的对象和引用。在此事件中,操纵会话状态是安全的,也就是说,新对象可以附加到它,对象可以被删除,并且可以自由更改对象上的单个属性,并且这些更改将在事件挂钩完成时被纳入到刷新过程中。

典型的SessionEvents.before_flush()挂钩将负责扫描集合Session.newSession.dirtySession.deleted,以查找将要发生变化的对象。

对于SessionEvents.before_flush()的示例,请参阅使用历史表进行版本控制和使用时间行进行版本控制等示例。

after_flush()

在 SQL 被发出进行刷新过程后,但是在被刷新的对象的状态被改变之前,会调用SessionEvents.after_flush()挂钩。也就是说,你仍然可以检查Session.newSession.dirtySession.deleted这些集合,看看刚刚刷新了什么,你也可以使用像AttributeState提供的历史跟踪功能来查看刚刚持久化了什么更改。在SessionEvents.after_flush()事件中,可以根据观察到的变化向数据库发出其他 SQL。

after_flush_postexec()

SessionEvents.after_flush_postexec()SessionEvents.after_flush() 之后不久被调用,但在考虑了刚刚发生的刷新后对象状态被修改的情况下调用。Session.newSession.dirtySession.deleted 集合通常在这里是完全空的。使用 SessionEvents.after_flush_postexec() 来检查已完成对象的标识映射并可能发出额外的 SQL。在这个钩子中,有能力对对象进行新的更改,这意味着 Session 将再次进入“dirty”状态;如果在此钩子中检测到新的更改,则会导致 Session 的机制再次刷新一次,如果在 Session.commit() 的上下文中调用刷新并检测到新的更改,则否则,挂起的更改将作为下一个正常刷新的一部分捆绑在一起。当钩子在 Session.commit() 中检测到新的更改时,计数器确保在每次调用时都添加新的状态时不会无限循环,以防止无休止的循环在这方面在经过 100 次迭代后停止。

Mapper 级别的刷新事件

除了刷新级别的钩子外,还有一组更细粒度的钩子,它们是基于每个对象的并且根据刷新过程中的 INSERT、UPDATE 或 DELETE 而分开的。这些是映射器持久性钩子,它们也非常受欢迎,但是需要更加谨慎地对待这些事件,因为它们在已经进行中的刷新过程的上下文中进行;在这里进行许多操作是不安全的。

事件包括:

  • MapperEvents.before_insert()
  • MapperEvents.after_insert()
  • MapperEvents.before_update()
  • MapperEvents.after_update()
  • MapperEvents.before_delete()
  • MapperEvents.after_delete()

注意

重要的是要注意,这些事件仅适用于会话刷新操作,而不适用于在 ORM-Enabled INSERT、UPDATE 和 DELETE 语句中描述的 ORM 级别的 INSERT/UPDATE/DELETE 功能。要拦截 ORM 级别的 DML,请使用SessionEvents.do_orm_execute()事件。

每个事件都会传递Mapper、映射对象本身以及正在用于发出 INSERT、UPDATE 或 DELETE 语句的Connection。这些事件的吸引力是显而易见的,因为如果一个应用程序想要将某些活动与特定类型的对象被插入时联系起来,那么钩子就非常具体;不像SessionEvents.before_flush()事件那样,不需要搜索像Session.new这样的集合以找到目标。然而,在调用这些事件时,表示将要发出的每个单独的 INSERT、UPDATE、DELETE 语句的 flush 计划已经已经决定,并且在此阶段不能做出任何更改。因此,对给定对象的唯一可能的更改是对对象行本地的属性进行。对对象或其他对象的任何其他更改将影响Session的状态,这将导致其无法正常工作。

不支持这些映射器级别持久性事件中的操作包括:

  • Session.add()
  • Session.delete()
  • 映射集合的附加、添加、删除、丢弃等操作。
  • 映射关系属性设置/删除事件,即someobject.related = someotherobject

传递Connection的原因是鼓励在此处执行简单的 SQL 操作,直接在Connection上,例如增加计数器或在日志表中插入额外行。

也有许多不需要在刷新事件中处理的每个对象操作。最常见的替代方法是简单地在对象的__init__()方法中与对象一起建立附加状态,例如创建与新对象关联的其他对象。使用如简单验证器中所述的验证器是另一种方法;这些函数可以拦截对属性的更改,并在响应属性更改时在目标对象上建立额外的状态更改。使用这两种方法,对象在到达刷新步骤之前处于正确的状态。

before_flush()

SessionEvents.before_flush() 钩子是应用程序希望确保在提交刷新时进行额外持久化更改时最常用的事件。使用SessionEvents.before_flush() 来操作对象以验证其状态,并在持久化之前组成额外的对象和引用。在此事件中,操作会话的状态是安全的,即,新对象可以附加到其中,对象可以被删除,并且可以自由更改对象上的单个属性,并且这些更改将在事件钩子完成时被引入到刷新过程中。

典型的SessionEvents.before_flush() 钩子将负责扫描集合Session.newSession.dirtySession.deleted,以查找将发生事情的对象。

有关SessionEvents.before_flush()的示例,请参见带有历史表的版本控制和使用时间行进行版本控制等示例。

after_flush()

SessionEvents.after_flush() 钩子在 flush 过程中的 SQL 已经被发出,但是在被刷新的对象状态被改变之前被调用。也就是说,您仍然可以检查 Session.newSession.dirtySession.deleted 集合,看看刚刚被刷新了什么,您还可以使用像 AttributeState 提供的历史跟踪功能来查看刚刚持久化的更改。在 SessionEvents.after_flush() 事件中,根据观察到的更改,可以向数据库发出其他 SQL。

after_flush_postexec()

SessionEvents.after_flush_postexec()SessionEvents.after_flush() 之后不久调用,但是在对象的状态已经修改以反映刚刚发生的刷新之后调用。这里 Session.newSession.dirtySession.deleted 集合通常完全为空。使用 SessionEvents.after_flush_postexec() 来检查最终化对象的标识映射,并可能发出其他 SQL。在这个钩子中,有能力对对象进行新的更改,这意味着 Session 将再次进入“dirty”状态;如果在 Session.commit() 的上下文中调用此钩子时检测到新的更改,那么Session 的机制会导致它再次刷新;否则,待定的更改将作为下一个正常刷新的一部分捆绑在一起。当钩子在 Session.commit() 中检测到新的更改时,计数器会在此方面的无限循环在 100 次迭代后停止,在这种情况下,如果 SessionEvents.after_flush_postexec() 钩子每次调用时都持续添加新的要刷新的状态,就会停止。

映射器级别的刷新事件

除了刷新级别的钩子外,还有一套更精细的钩子,因为它们是基于每个对象调用的,并根据刷新过程中的 INSERT、UPDATE 或 DELETE 进行分组。这些是映射器持久性钩子,它们也非常受欢迎,但是这些事件需要更谨慎地处理,因为它们在已经进行的刷新过程的上下文中进行;许多操作在这里进行不安全。

事件包括:

  • MapperEvents.before_insert()
  • MapperEvents.after_insert()
  • MapperEvents.before_update()
  • MapperEvents.after_update()
  • MapperEvents.before_delete()
  • MapperEvents.after_delete()

注意

重要的是要注意,这些事件适用于会话刷新操作,而不是描述的 ORM 级别的 INSERT/UPDATE/DELETE 功能 ORM-Enabled INSERT, UPDATE, and DELETE statements。要拦截 ORM 级别的 DML,请使用SessionEvents.do_orm_execute()事件。

每个事件都会传递Mapper、映射对象本身和用于发出 INSERT、UPDATE 或 DELETE 语句的Connection。这些事件的吸引力是显而易见的,因为如果应用程序想要将某些活动与在 INSERT 时持久化特定类型的对象绑定起来,这个钩子就非常具体;与SessionEvents.before_flush()事件不同,不需要搜索像Session.new这样的集合来找到目标。然而,在调用这些事件时,表示要发出的每个单独的 INSERT、UPDATE、DELETE 语句的刷新计划已经已经确定,在此阶段无法进行任何更改。因此,甚至可能对给定对象进行的唯一更改是对对象行的本地属性。对于对象或其他对象的任何其他更改都将影响到Session的状态,这将导致其无法正常工作。

在这些映射器级别的持久性事件中不支持的操作包括:

  • Session.add()
  • Session.delete()
  • 映射的集合追加、添加、移除、删除、丢弃等操作。
  • 映射的关系属性设置/删除事件,即someobject.related = someotherobject

传递Connection的原因是鼓励在这里进行简单的 SQL 操作,直接在Connection上进行,比如增加计数器或在日志表中插入额外行。

还有许多不需要在刷新事件中处理的每个对象操作。最常见的替代方法是在对象的__init__()方法中简单地建立额外状态,比如创建要与新对象关联的其他对象。另一种方法是使用简单验证器中描述的验证器;这些函数可以拦截属性的更改,并在响应属性更改时在目标对象上建立额外的状态更改。使用这两种方法,对象在进入刷新步骤之前就处于正确状态。

对象生命周期事件

事件的另一个用例是跟踪对象的生命周期。这指的是首次介绍的状态,即快速介绍对象状态。

所有上述状态都可以通过事件完全跟踪。每个事件代表一个不同的状态转换,意味着起始状态和目标状态都是被跟踪的一部分。除了初始瞬态事件之外,所有事件都是以Session对象或类的形式,意味着它们可以与特定的Session对象关联:

代码语言:javascript复制
from sqlalchemy import event
from sqlalchemy.orm import Session

session = Session()

@event.listens_for(session, "transient_to_pending")
def object_is_pending(session, obj):
    print("new pending: %s" % obj)

或者与Session类本身一起,以及与特定的sessionmaker一起,这可能是最有用的形式:

代码语言:javascript复制
from sqlalchemy import event
from sqlalchemy.orm import sessionmaker

maker = sessionmaker()

@event.listens_for(maker, "transient_to_pending")
def object_is_pending(session, obj):
    print("new pending: %s" % obj)

当然,监听器可以堆叠在一个函数之上,这很常见。例如,要跟踪进入持久状态的所有对象:

代码语言:javascript复制
@event.listens_for(maker, "pending_to_persistent")
@event.listens_for(maker, "deleted_to_persistent")
@event.listens_for(maker, "detached_to_persistent")
@event.listens_for(maker, "loaded_as_persistent")
def detect_all_persistent(session, instance):
    print("object is now persistent: %s" % instance)
瞬态

当所有映射对象首次构建时,它们都是瞬态的。在此状态下,对象单独存在,并且不与任何Session相关联。对于这种初始状态,没有特定的“转换”事件,因为没有Session,但是如果想要拦截任何瞬态对象被创建时,InstanceEvents.init() 方法可能是最好的事件。此事件适用于特定的类或超类。例如,要拦截特定声明基类的所有新对象:

代码语言:javascript复制
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import event

class Base(DeclarativeBase):
    pass

@event.listens_for(Base, "init", propagate=True)
def intercept_init(instance, args, kwargs):
    print("new transient: %s" % instance)
瞬态到挂起

当瞬态对象首次通过Session.add()Session.add_all()方法与Session关联时,瞬态对象变为挂起。对象也可能作为显式添加的引用对象的“级联”的结果之一而成为Session的一部分。可以使用SessionEvents.transient_to_pending()事件检测瞬态到挂起的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "transient_to_pending")
def intercept_transient_to_pending(session, object_):
    print("transient to pending: %s" % object_)
挂起到持久

当刷新继续并且针对实例进行 INSERT 语句时,挂起对象变为持久。对象现在具有标识键。使用SessionEvents.pending_to_persistent()事件跟踪挂起到持久的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "pending_to_persistent")
def intercept_pending_to_persistent(session, object_):
    print("pending to persistent: %s" % object_)
挂起到瞬态

如果在挂起对象刷新之前调用Session.rollback()方法,或者在刷新对象之前调用Session.expunge()方法,则挂起对象可以恢复为瞬态。使用SessionEvents.pending_to_transient()事件跟踪挂起到瞬态的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "pending_to_transient")
def intercept_pending_to_transient(session, object_):
    print("transient to pending: %s" % object_)
加载为持久对象

当从数据库加载对象时,对象可以直接进入 Session 中的 persistent 状态。跟踪这种状态转换与跟踪对象的加载是同义的,并且等同于使用 InstanceEvents.load() 实例级事件。然而,SessionEvents.loaded_as_persistent() 事件作为一个针对会话的钩子,用于拦截对象通过这种特定途径进入持久状态:

代码语言:javascript复制
@event.listens_for(sessionmaker, "loaded_as_persistent")
def intercept_loaded_as_persistent(session, object_):
    print("object loaded into persistent state: %s" % object_)
持久到瞬态

当对象处于持久状态时,如果调用了 Session.rollback() 方法,该对象会恢复到瞬态状态,前提是它最初是作为待定对象添加的事务。在回滚的情况下,使该对象持久的 INSERT 语句将被回滚,并且该对象将从 Session 中驱逐出去,再次变为瞬态。使用 SessionEvents.persistent_to_transient() 事件钩子来跟踪从持久状态恢复到瞬态状态的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_transient")
def intercept_persistent_to_transient(session, object_):
    print("persistent to transient: %s" % object_)
持久到已删除

当标记为删除的对象在刷新过程中从数据库中删除时,持久对象进入了 deleted 状态。请注意,这与调用 Session.delete() 方法删除目标对象时不同Session.delete() 方法只是标记对象为删除;直到刷新进行时,实际的 DELETE 语句才会被发出。在刷新之后,目标对象将处于“deleted”状态。

在“deleted”状态下,对象与 Session 仅有轻微关联。它不在标识映射中,也不在指示它何时待删除的 Session.deleted 集合中。

从“deleted”状态,对象可以在事务提交时进入分离状态,或者如果事务回滚,则返回持久状态。

使用 SessionEvents.persistent_to_deleted() 跟踪从持久到已删除的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_deleted")
def intercept_persistent_to_deleted(session, object_):
    print("object was DELETEd, is now in deleted state: %s" % object_)
删除到分离

当会话的事务提交后,删除的对象会变成分离。在调用Session.commit()方法后,数据库事务已经完成,Session现在完全丢弃了删除的对象并删除了所有与之相关的关联。使用SessionEvents.deleted_to_detached()跟踪删除到分离的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "deleted_to_detached")
def intercept_deleted_to_detached(session, object_):
    print("deleted to detached: %s" % object_)

注意

当对象处于删除状态时,可通过inspect(object).deleted访问InstanceState.deleted属性,返回 True。然而,当对象被分离时,InstanceState.deleted将再次返回 False。要检测对象是否已被删除,无论它是否分离,都可以使用InstanceState.was_deleted访问器。

持久到分离

当对象使用Session.expunge()Session.expunge_all()Session.close()方法与Session解除关联时,持久对象将变为分离。

注意

如果应用程序解除引用并由于垃圾回收而丢弃了拥有的Session,则对象也可能隐式分离。在这种情况下,不会触发任何事件

使用SessionEvents.persistent_to_detached()事件跟踪对象从持久到分离的移动:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_detached")
def intercept_persistent_to_detached(session, object_):
    print("object became detached: %s" % object_)
分离到持久

当分离的对象使用Session.add()或等效方法重新关联到会话时,它将变成持久对象。使用SessionEvents.detached_to_persistent()事件跟踪从分离返回到持久的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "detached_to_persistent")
def intercept_detached_to_persistent(session, object_):
    print("object became persistent again: %s" % object_)
删除到持久

当用于 DELETE 的事务使用Session.rollback()方法回滚时,已删除对象可以恢复为持久状态。使用SessionEvents.deleted_to_persistent()事件跟踪已删除对象移回持久状态:

代码语言:javascript复制
@event.listens_for(sessionmaker, "deleted_to_persistent")
def intercept_deleted_to_persistent(session, object_):
    print("deleted to persistent: %s" % object_)
暂时

所有映射对象在首次构造时都作为暂时状态开始。在这种状态下,对象单独存在,并且不与任何Session相关联。对于这种初始状态,没有特定的“转换”事件,因为没有Session,但是如果想要拦截任何暂时对象被创建的情况,InstanceEvents.init()方法可能是最好的事件。此事件适用于特定类或超类。例如,要拦截特定声明基类的所有新对象:

代码语言:javascript复制
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import event

class Base(DeclarativeBase):
    pass

@event.listens_for(Base, "init", propagate=True)
def intercept_init(instance, args, kwargs):
    print("new transient: %s" % instance)
暂时到待定

当暂时对象首次通过Session.add()Session.add_all()方法与Session相关联时,暂时对象变为待定状态。对象也可能作为引用对象的“级联”结果成为Session的一部分,该引用对象已明确添加。可以使用SessionEvents.transient_to_pending()事件检测从暂时到待定的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "transient_to_pending")
def intercept_transient_to_pending(session, object_):
    print("transient to pending: %s" % object_)
待定到持久

待定对象在执行冲洗并为该实例执行插入语句时变为持久状态。对象现在具有标识键。使用SessionEvents.pending_to_persistent()事件跟踪待定对象到持久状态的转换:

代码语言:javascript复制
@event.listens_for(sessionmaker, "pending_to_persistent")
def intercept_pending_to_persistent(session, object_):
    print("pending to persistent: %s" % object_)
待定到暂时

如果在待定对象被刷新之前调用了Session.rollback()方法,或者在对象被刷新之前调用了Session.expunge()方法,则待定对象可以恢复到瞬态状态。使用SessionEvents.pending_to_transient()事件跟踪从待定到瞬态的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "pending_to_transient")
def intercept_pending_to_transient(session, object_):
    print("transient to pending: %s" % object_)
加载为持久化

对象可以直接以持久化状态出现在Session中,当它们从数据库中加载时。跟踪这种状态转换与跟踪对象的加载是同义的,并且与使用InstanceEvents.load()实例级事件是同义的。但是,提供了SessionEvents.loaded_as_persistent()事件作为一个会话中心的钩子,用于拦截通过这种特定途径进入持久化状态的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "loaded_as_persistent")
def intercept_loaded_as_persistent(session, object_):
    print("object loaded into persistent state: %s" % object_)
持久化到瞬态

如果在对象首次被添加为待定的事务中调用了Session.rollback()方法,则持久化对象可以恢复到瞬态状态。在回滚的情况下,使该对象持久化的 INSERT 语句被回滚,对象被从Session中驱逐,再次成为瞬态。使用SessionEvents.persistent_to_transient()事件钩子跟踪从持久化到瞬态的对象:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_transient")
def intercept_persistent_to_transient(session, object_):
    print("persistent to transient: %s" % object_)
持久化到已删除

在刷新过程中,如果标记为删除的对象从数据库中被删除,则持久化对象进入已删除状态。请注意,这调用Session.delete()方法删除目标对象时不同。Session.delete()方法仅标记对象以进行删除;直到刷新进行之后,实际的 DELETE 语句才会被发出。在刷新之后,目标对象的“已删除”状态才存在。

在“删除”状态中,对象与Session仅具有较弱的关联。它不在标识映射中,也不在指向它曾经等待删除的Session.deleted集合中。

从“删除”状态,对象可以通过提交事务进入分离状态,或者如果事务被回滚,则返回持久状态。

使用SessionEvents.persistent_to_deleted()来追踪持久到删除的转变:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_deleted")
def intercept_persistent_to_deleted(session, object_):
    print("object was DELETEd, is now in deleted state: %s" % object_)
删除到分离

当会话的事务提交后,被删除的对象会变成分离状态。在调用Session.commit()方法后,数据库事务已经最终化,Session现在完全丢弃了被删除的对象并移除了所有与其相关的关联。使用SessionEvents.deleted_to_detached()来追踪从删除到分离的转变:

代码语言:javascript复制
@event.listens_for(sessionmaker, "deleted_to_detached")
def intercept_deleted_to_detached(session, object_):
    print("deleted to detached: %s" % object_)

注意

当对象处于删除状态时,可以通过inspect(object).deleted访问的InstanceState.deleted属性返回 True。但是当对象分离时,InstanceState.deleted将再次返回 False。要检测对象是否已被删除,无论它是否分离,请使用InstanceState.was_deleted访问器。

持久到分离

当对象与Session取消关联时,通过Session.expunge()Session.expunge_all()Session.close()方法,持久对象会变成分离状态。

注意

如果由于垃圾回收应用程序取消引用并丢弃了拥有对象的Session,则对象也可能隐式分离。在这种情况下,不会发出任何事件

使用SessionEvents.persistent_to_detached()事件跟踪对象从持久化到分离的移动:

代码语言:javascript复制
@event.listens_for(sessionmaker, "persistent_to_detached")
def intercept_persistent_to_detached(session, object_):
    print("object became detached: %s" % object_)
分离到持久化

当将分离的对象重新关联到会话时,该分离对象变为持久化状态,可使用Session.add()或等效方法。跟踪对象从分离状态回到持久化状态时,请使用SessionEvents.detached_to_persistent()事件:

代码语言:javascript复制
@event.listens_for(sessionmaker, "detached_to_persistent")
def intercept_detached_to_persistent(session, object_):
    print("object became persistent again: %s" % object_)
删除到持久化

当以 DELETE 方式删除对象的事务被使用Session.rollback()方法回滚时,删除对象可以恢复到持久化状态。跟踪已删除对象从删除状态返回持久化状态,请使用SessionEvents.deleted_to_persistent()事件:

代码语言:javascript复制
@event.listens_for(sessionmaker, "deleted_to_persistent")
def intercept_deleted_to_persistent(session, object_):
    print("deleted to persistent: %s" % object_)

事务事件

事务事件允许应用程序在Session级别发生事务边界以及SessionConnection对象上更改事务状态时得到通知。

  • SessionEvents.after_transaction_create(), SessionEvents.after_transaction_end() - 这些事件跟踪Session的逻辑事务范围,与个别数据库连接无关。这些事件旨在帮助集成诸如zope.sqlalchemy之类的事务跟踪系统。当应用程序需要将某些外部范围与Session的事务范围对齐时,请使用这些事件。这些钩子反映了Session的“嵌套”事务行为,因为它们不仅跟踪逻辑“子事务”,还跟踪“嵌套”(例如 SAVEPOINT)事务。
  • SessionEvents.before_commit(), SessionEvents.after_commit(), SessionEvents.after_begin(), SessionEvents.after_rollback(), SessionEvents.after_soft_rollback() - 这些事件允许从数据库连接的角度跟踪事务事件。特别是SessionEvents.after_begin() 是一个每个连接的事件;一个维护多个连接的 Session 将在当前事务中使用这些连接时为每个连接单独发出此事件。然后回滚和提交事件是指 DBAPI 连接本身何时直接收到回滚或提交指令。

属性更改事件

属性更改事件允许拦截对象上特定属性被修改的情况。这些事件包括AttributeEvents.set(), AttributeEvents.append(), 和 AttributeEvents.remove()。这些事件非常有用,特别是用于每个对象的验证操作;然而,通常更方便使用“验证器”钩子,该钩子在幕后使用这些钩子;请参阅简单验证器 了解背景信息。属性事件也在反向引用的机制后面。一个示例说明了属性事件的使用在属性检测。

Session API

原文:docs.sqlalchemy.org/en/20/orm/session_api.html

Session 和 sessionmaker()

对象名称

描述

ORMExecuteState

表示对Session.execute()方法的调用,作为传递给SessionEvents.do_orm_execute()事件钩子的参数。

Session

管理 ORM 映射对象的持久化操作。

sessionmaker

可配置的Session工厂。

SessionTransaction

一个Session级别的事务。

SessionTransactionOrigin

表示SessionTransaction的来源。

代码语言:javascript复制
class sqlalchemy.orm.sessionmaker

可配置的Session工厂。

sessionmaker工厂在调用时生成新的Session对象,在此处建立的配置参数的基础上创建它们。

例如:

代码语言:javascript复制
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# an Engine, which the Session will use for connection
# resources
engine = create_engine('postgresql psycopg2://scott:tiger@localhost/')

Session = sessionmaker(engine)

with Session() as session:
    session.add(some_object)
    session.add(some_other_object)
    session.commit()

上下文管理器的使用是可选的;否则,通过Session.close()方法可以显式关闭返回的Session对象。使用try:/finally:块是可选的,但是会确保即使存在数据库错误,关闭也会发生:

代码语言:javascript复制
session = Session()
try:
    session.add(some_object)
    session.add(some_other_object)
    session.commit()
finally:
    session.close()

sessionmaker充当Engine充当Connection对象的工厂的工厂。以这种方式,它还包括一个sessionmaker.begin()方法,提供一个上下文管理器,该管理器既开始又提交事务,完成后关闭Session,如果出现任何错误,则回滚事务:

代码语言:javascript复制
Session = sessionmaker(engine)

with Session.begin() as session:
    session.add(some_object)
    session.add(some_other_object)
# commits transaction, closes session

新版本 1.4 中新增。

当调用sessionmaker来构造一个Session时,也可以传递关键字参数给方法;这些参数将覆盖全局配置的参数。下面我们使用一个绑定到某个Enginesessionmaker来生成一个Session,而该Session则绑定到从该引擎获取的特定Connection上:

代码语言:javascript复制
Session = sessionmaker(engine)

# bind an individual session to a connection

with engine.connect() as connection:
    with Session(bind=connection) as session:
        # work with session

该类还包括一个方法sessionmaker.configure(),用于指定工厂的其他关键字参数,这些参数将对生成的后续Session对象生效。通常用于在首次使用之前将一个或多个Engine对象与现有的sessionmaker工厂关联起来:

代码语言:javascript复制
# application starts, sessionmaker does not have
# an engine bound yet
Session = sessionmaker()

# ... later, when an engine URL is read from a configuration
# file or other events allow the engine to be created
engine = create_engine('sqlite:///foo.db')
Session.configure(bind=engine)

sess = Session()
# work with session

另请参阅

打开和关闭会话 - 关于使用sessionmaker创建会话的介绍性文本。

成员

call(), init(), begin(), close_all(), configure(), identity_key(), object_session()

类签名

sqlalchemy.orm.sessionmakersqlalchemy.orm.session._SessionClassMethods, typing.Generic

代码语言:javascript复制
method __call__(**local_kw: Any) → _S

使用在这个sessionmaker中建立的配置生成一个新的Session对象。

在 Python 中,当对象“被调用”时,会调用__call__方法,其方式与函数相同:

代码语言:javascript复制
Session = sessionmaker(some_engine)
session = Session()  # invokes sessionmaker.__call__()
代码语言:javascript复制
method __init__(bind: Optional[_SessionBind] = None, *, class_: Type[_S] = <class 'sqlalchemy.orm.session.Session'>, autoflush: bool = True, expire_on_commit: bool = True, info: Optional[_InfoType] = None, **kw: Any)

构造一个新的sessionmaker

这里的所有参数,除了class_之外,都与Session直接接受的参数相对应。有关参数的更多详细信息,请参阅Session.__init__()文档字符串。

参数:

  • bind – 一个Engine或其他Connectable,新创建的Session对象将与之关联。
  • class_ – 用于创建新的Session对象的类。默认为Session
  • autoflush – 用于新创建的Session对象的自动刷新设置。 另请参阅 刷新 - 关于自动刷新的额外背景信息
  • expire_on_commit=True – 用于新创建的Session对象的Session.expire_on_commit设置。
  • info – 可选信息字典,将通过Session.info可用。请注意,当指定info参数进行特定Session构造操作时,此字典将被更新,而不是替换。
  • **kw – 所有其他关键字参数都传递给新创建的Session对象的构造函数。
代码语言:javascript复制
method begin() → AbstractContextManager[_S]

生成一个上下文管理器,既提供一个新的Session,又提供一个提交的事务。

例如:

代码语言:javascript复制
Session = sessionmaker(some_engine)

with Session.begin() as session:
    session.add(some_object)

# commits transaction, closes session

版本 1.4 中的新功能。

代码语言:javascript复制
classmethod close_all() → None

继承自 sqlalchemy.orm.session._SessionClassMethods.close_all 方法的 sqlalchemy.orm.session._SessionClassMethods

关闭内存中的所有会话。

自版本 1.3 起已弃用:Session.close_all()方法已弃用,并将在将来的版本中删除。请参考close_all_sessions()

代码语言:javascript复制
method configure(**new_kw: Any) → None

(重新)配置此 sessionmaker 的参数。

例如:

代码语言:javascript复制
Session = sessionmaker()

Session.configure(bind=create_engine('sqlite://'))
代码语言:javascript复制
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]

继承自 sqlalchemy.orm.session._SessionClassMethods.identity_key 方法的 sqlalchemy.orm.session._SessionClassMethods

返回一个标识键。

这是identity_key()的别名。

代码语言:javascript复制
classmethod object_session(instance: object) → Session | None

继承自 sqlalchemy.orm.session._SessionClassMethods.object_session 方法的 sqlalchemy.orm.session._SessionClassMethods

返回一个对象所属的Session

这是object_session()的别名。

代码语言:javascript复制
class sqlalchemy.orm.ORMExecuteState

表示对Session.execute()方法的调用,作为传递给SessionEvents.do_orm_execute()事件钩子的参数。

版本 1.4 中的新功能。

另请参阅

执行事件 - 如何使用SessionEvents.do_orm_execute()的顶级文档。

成员

init(), all_mappers, bind_arguments, bind_mapper, execution_options, invoke_statement(), is_column_load, is_delete, is_executemany, is_from_statement, is_insert, is_orm_statement, is_relationship_load, is_select, is_update, lazy_loaded_from, load_options, loader_strategy_path, local_execution_options, parameters, session, statement, update_delete_options, update_execution_options(), user_defined_options

类签名

sqlalchemy.orm.ORMExecuteState (sqlalchemy.util.langhelpers.MemoizedSlots)

代码语言:javascript复制
method __init__(session: Session, statement: Executable, parameters: _CoreAnyExecuteParams | None, execution_options: _ExecuteOptions, bind_arguments: _BindArguments, compile_state_cls: Type[ORMCompileState] | None, events_todo: List[_InstanceLevelDispatch[Session]])

构造一个新的ORMExecuteState

此对象是在内部构造的。

代码语言:javascript复制
attribute all_mappers

返回此语句顶层涉及的所有Mapper对象的序列。

“顶级”指的是那些在select()查询的结果集行中表示的Mapper对象,或者在update()delete()查询中,是 UPDATE 或 DELETE 的主体。

版本 1.4.0b2 中的新内容。

另见

ORMExecuteState.bind_mapper

代码语言:javascript复制
attribute bind_arguments: _BindArguments

字典作为 Session.execute.bind_arguments 字典传递。

此字典可由扩展用于 Session 以传递将有助于确定一组数据库连接中的哪一个应该用于调用此语句的参数。

代码语言:javascript复制
attribute bind_mapper

返回是主“绑定”映射器的 Mapper

对于调用 ORM 语句的 ORMExecuteState 对象,即 ORMExecuteState.is_orm_statement 属性为 True 的情况,此属性将返回被视为语句的“主”映射器。术语“绑定映射器”指的是 Session 对象可能“绑定”到多个映射类键入的多个 Engine 对象,并且“绑定映射器”确定将选择哪个 Engine 对象。

对于针对单个映射类调用的语句,ORMExecuteState.bind_mapper 旨在是获取此映射器的可靠方法。

版本 1.4.0b2 中的新功能。

另请参阅

ORMExecuteState.all_mappers

代码语言:javascript复制
attribute execution_options: _ExecuteOptions

当前执行选项的完整字典。

这是语句级选项与本地传递的执行选项的合并。

另请参阅

ORMExecuteState.local_execution_options

Executable.execution_options()

ORM 执行选项

代码语言:javascript复制
method invoke_statement(statement: Executable | None = None, params: _CoreAnyExecuteParams | None = None, execution_options: OrmExecuteOptionsParameter | None = None, bind_arguments: _BindArguments | None = None) → Result[Any]

执行由此 ORMExecuteState 表示的语句,而不重新调用已经进行过的事件。

此方法本质上执行当前语句的可重入执行,即当前调用 SessionEvents.do_orm_execute() 事件。这样做的用例是为了事件处理程序想要重写如何返回最终 Result 对象,比如从离线缓存检索结果或者将结果从多次执行中连接起来的方案。

当实际处理程序函数在 SessionEvents.do_orm_execute() 中返回 Result 对象,并且传播到调用 Session.execute() 方法的地方时,Session.execute() 方法的其余部分将被抢占,并且 Result 对象将立即返回给 Session.execute() 的调用者。

参数:

  • statement – 可选的语句,用于代替当前由 ORMExecuteState.statement 表示的语句。
  • params – 可选的参数字典或参数列表将合并到此 ORMExecuteState 的现有 ORMExecuteState.parameters 中。 2.0 版更改:接受参数字典列表进行 executemany 执行。
  • execution_options – 可选的执行选项字典将合并到此 ORMExecuteState 的现有 ORMExecuteState.execution_options 中。
  • bind_arguments – 可选的 bind_arguments 字典将在此 ORMExecuteState 的当前 ORMExecuteState.bind_arguments 中合并。

返回:

一个带有 ORM 级结果的 Result 对象。

另见

重新执行语句 - 关于 ORMExecuteState.invoke_statement() 的适当用法的背景和示例。

代码语言:javascript复制
attribute is_column_load

如果操作是刷新现有 ORM 对象上的基于列的属性,则返回 True。

在诸如 Session.refresh() 的操作期间发生,以及当由 defer() 推迟的属性正在加载时,或者由 Session.expire() 直接或通过提交操作而过期的属性正在加载时。

处理程序在进行此类操作时很可能不希望向查询添加任何选项,因为查询应该是直接的主键获取,不应该有任何额外的 WHERE 条件,并且实例旅行的加载器选项已经添加到查询中。

版本 1.4.0b2 中的新功能。

另请参阅

ORMExecuteState.is_relationship_load

代码语言:javascript复制
attribute is_delete

如果这是一个 DELETE 操作,则返回 True。

2.0.30 版本中的更改:- 该属性对 Select.from_statement() 构造也是真的,该构造本身针对 Delete 构造,例如 select(Entity).from_statement(delete(..))

代码语言:javascript复制
attribute is_executemany

如果参数是一个包含多个字典且字典数量大于一个的列表,则返回 True。

版本 2.0 中的新功能。

代码语言:javascript复制
attribute is_from_statement

如果此操作是 Select.from_statement() 操作,则返回 True。

这与 ORMExecuteState.is_select 独立,因为 select().from_statement() 构造也可以与 INSERT/UPDATE/DELETE RETURNING 类型的语句一起使用。ORMExecuteState.is_select 仅在 Select.from_statement() 本身针对 Select 构造时设置。

版本 2.0.30 中的新功能。

代码语言:javascript复制
attribute is_insert

如果这是一个 INSERT 操作,则返回 True。

在 2.0.30 版本中更改: - 该属性对Select.from_statement()构造也为 True,该构造本身针对Insert构造,例如select(Entity).from_statement(insert(..))

代码语言:javascript复制
attribute is_orm_statement

如果操作是 ORM 语句,则返回 True。

这表示所调用的 select()、insert()、update()或 delete()包含 ORM 实体作为主体。对于没有 ORM 实体,而只引用Table元数据的语句,它被调用为核心 SQL 语句,并且不发生 ORM 级别的自动化。

代码语言:javascript复制
attribute is_relationship_load

如果此加载正在代表关系加载对象,则返回 True。

这意味着,加载程序实际上是一个 LazyLoader、SelectInLoader、SubqueryLoader 或类似的加载程序,并且整个发出的 SELECT 语句都是代表关系加载的。

处理程序很可能不希望在发生此类操作时向查询添加任何选项,因为加载程序选项已经能够传播到关系加载程序,并且应已存在。

另请参阅

ORMExecuteState.is_column_load

代码语言:javascript复制
attribute is_select

如果这是一个 SELECT 操作,则返回 True。

在 2.0.30 版本中更改: - 该属性对Select.from_statement()构造也为 True,该构造本身针对Select构造,例如select(Entity).from_statement(select(..))

代码语言:javascript复制
attribute is_update

如果这是一个 UPDATE 操作,则返回 True。

在 2.0.30 版本中更改: - 该属性对Select.from_statement()构造也为 True,该构造本身针对Update构造,例如select(Entity).from_statement(update(..))

代码语言:javascript复制
attribute lazy_loaded_from

正在使用此语句执行进行延迟加载操作的InstanceState

此属性的主要理由是支持水平分片扩展,在此扩展创建的特定查询执行时间钩子中可用。为此,该属性仅打算在查询执行时间具有意义,而且重要的是不是在此之前的任何时间,包括查询编译时间。

代码语言:javascript复制
attribute load_options

返回将用于此执行的load_options

代码语言:javascript复制
attribute loader_strategy_path

返回当前加载路径的PathRegistry

此对象表示查询中关系的“路径”,当加载特定对象或集合时。

代码语言:javascript复制
attribute local_execution_options: _ExecuteOptions

Session.execute() 方法传递的执行选项的字典视图。

这不包括与被调用语句相关的选项。

另请参阅

ORMExecuteState.execution_options

代码语言:javascript复制
attribute parameters: _CoreAnyExecuteParams | None

传递给 Session.execute() 方法的参数字典。

代码语言:javascript复制
attribute session: Session

正在使用的 Session

代码语言:javascript复制
attribute statement: Executable

被调用的 SQL 语句。

对于像从 Query 检索到的 ORM 选择,这是从 ORM 查询生成的 select 的一个实例。

代码语言:javascript复制
attribute update_delete_options

返回将用于此执行的 update_delete_options。

代码语言:javascript复制
method update_execution_options(**opts: Any) → None

使用新值更新本地执行选项。

代码语言:javascript复制
attribute user_defined_options

与被调用语句关联的 UserDefinedOptions 序列。

代码语言:javascript复制
class sqlalchemy.orm.Session

管理 ORM 映射对象的持久化操作。

Session 不适用于并发线程。有关详情,请参阅会话是否线程安全? AsyncSession 是否安全可在并发任务中共享?。

关于 Session 的使用范例请参见使用 Session。

成员

init(), add(), add_all(), begin(), begin_nested(), bind_mapper(), bind_table(), bulk_insert_mappings(), bulk_save_objects(), bulk_update_mappings(), close(), close_all(), commit(), connection(), delete(), deleted, dirty, enable_relationship_loading(), execute(), expire(), expire_all(), expunge(), expunge_all(), flush(), get(), get_bind(), get_nested_transaction(), get_one(), get_transaction(), identity_key(), identity_map, in_nested_transaction(), in_transaction(), info, invalidate(), is_active, is_modified(), merge(), new, no_autoflush, object_session(), prepare(), query(), refresh(), reset(), rollback(), scalar(), scalars()

类签名

sqlalchemy.orm.Session (sqlalchemy.orm.session._SessionClassMethods, sqlalchemy.event.registry.EventTarget)

代码语言:javascript复制
method __init__(bind: _SessionBind | None = None, *, autoflush: bool = True, future: Literal[True] = True, expire_on_commit: bool = True, autobegin: bool = True, twophase: bool = False, binds: Dict[_SessionBindKey, _SessionBind] | None = None, enable_baked_queries: bool = True, info: _InfoType | None = None, query_cls: Type[Query[Any]] | None = None, autocommit: Literal[False] = False, join_transaction_mode: JoinTransactionMode = 'conditional_savepoint', close_resets_only: bool | _NoArg = _NoArg.NO_ARG)

构建一个新的 Session

还请参阅 sessionmaker 函数,该函数用于生成具有给定参数集的产生 Session 的可调用对象。

参数:

autoflush

当为True时,所有查询操作将在继续之前对此Session发出一个Session.flush()调用。这是一个方便的功能,使得不需要重复调用Session.flush()以便数据库查询检索结果。

另请参阅

刷新 - 自动刷新的额外背景

autobegin

当请求由操作请求数据库访问时,自动启动事务(即相当于调用Session.begin())。默认为True。将其设置为False以防止Session在构造后隐式开始事务,以及在调用任何Session.rollback()Session.commit()Session.close()方法后隐式开始事务。

2.0 版中的新功能。

另请参阅

禁用自动启动以防止隐式事务

bind – 此Session应绑定到的可选EngineConnection。当指定时,此会话执行的所有 SQL 操作都将通过此连接执行。

binds

一个字典,可以指定任意数量的EngineConnection对象作为每个实体连接的源。字典的键由任何一系列映射类、任意的用作映射类基础的 Python 类、Table对象和Mapper对象组成。然后字典的值是Engine或较少常见的Connection对象的实例。针对特定映射类进行的操作将查询此字典,以确定用于特定 SQL 操作的最接近匹配实体为何。解析的完整启发式方法在Session.get_bind()中描述。用法如下:

代码语言:javascript复制
Session = sessionmaker(binds={
    SomeMappedClass: create_engine('postgresql psycopg2://engine1'),
    SomeDeclarativeBase: create_engine('postgresql psycopg2://engine2'),
    some_mapper: create_engine('postgresql psycopg2://engine3'),
    some_table: create_engine('postgresql psycopg2://engine4'),
    })

另请参阅

分区策略(例如每个会话的多个数据库后端)

Session.bind_mapper()

Session.bind_table()

Session.get_bind()

class_ – 指定除了 sqlalchemy.orm.session.Session 之外的另一个类,该类应该由返回的类使用。 这是唯一一个本地于 sessionmaker 函数的参数,并且不直接发送到 Session 的构造函数。

enable_baked_queries

经典; 默认为 True。 由 sqlalchemy.ext.baked 扩展消耗的一个参数,用于确定是否应该缓存“烘焙查询”,正如该扩展的正常操作一样。 当设置为 False 时,该特定扩展所使用的缓存被禁用。

从版本 1.4 开始更改: sqlalchemy.ext.baked 扩展是遗留的,不被 SQLAlchemy 的任何内部使用。 因此,该标志仅影响在其自己的代码中明确使用此扩展的应用程序。

expire_on_commit

默认为 True。 当为 True 时,每次 commit() 后所有实例都将完全过期,以便在完成事务后的所有属性/对象访问从最新的数据库状态加载。

另请参阅 提交

future

已弃用; 此标志始终为 True。

另请参阅

SQLAlchemy 2.0 - 主要迁移指南

info – 可选的与此 Session 关联的任意数据的字典。 可通过 Session.info 属性访问。 请注意,该字典在构造时被复制,因此对每个 Session 字典的修改将局限于该 Session

query_cls – 应该用于创建新的查询对象的类,由 Session.query() 方法返回。 默认为 Query

twophase – 当为True时,所有事务都将作为“两阶段”事务启动,即使用正在使用的数据库的“两阶段”语义以及 XID。在每个附加数据库上发出了所有附加数据库的flush()之后,在commit()期间,将调用每个数据库的TwoPhaseTransactionTwoPhaseTransaction.prepare()方法。这允许每个数据库在提交每个事务之前回滚整个事务。

autocommitautocommit关键字出现是为了向后兼容,但必须保持其默认值为False

join_transaction_mode

描述了在给定绑定是已经在此Session范围之外开始事务的Connection时要采取的事务行为;换句话说,Connection.in_transaction()方法返回 True。

以下行为仅在Session实际使用给定的连接时才生效;也就是说,诸如Session.execute()Session.connection()等方法实际上被调用:

  • "conditional_savepoint" - 这是默认值。如果给定的Connection在事务中开始但没有保存点,则使用"rollback_only"。如果Connection此外还在保存点中,换句话说,Connection.in_nested_transaction()方法返回 True,则使用"create_savepoint""conditional_savepoint" 行为试图利用 SAVEPOINT 以保持现有事务的状态不变,但只有在已经存在 SAVEPOINT 的情况下才会这样做;否则,不假定正在使用的后端具有足够的 SAVEPOINT 支持,因为此功能的可用性会有所变化。 "conditional_savepoint" 还试图与之前的 Session 行为建立大致的向后兼容性,适用于未设置特定模式的应用程序。建议使用其中一种显式设置。
  • "create_savepoint" - Session 将在所有情况下使用 Connection.begin_nested() 来创建自己的事务。该事务本质上“在顶部”上使用给定 Connection 上已打开的任何现有事务;如果底层数据库和正在使用的驱动程序完全且不破损地支持 SAVEPOINT,则外部事务将在 Session 的生命周期内保持不受影响。 "create_savepoint" 模式对于将 Session 集成到测试套件中并使外部启动的事务保持不受影响是最有用的;但是,它依赖于底层驱动程序和数据库对 SAVEPOINT 的正确支持。 提示 当使用 SQLite 时,Python 3.11 中包含的 SQLite 驱动程序在某些情况下未正确处理 SAVEPOINTs,需要使用解决方法。详见 Serializable isolation / Savepoints / Transactional DDL 和 Serializable isolation / Savepoints / Transactional DDL (asyncio version) 部分。
  • "control_fully" - Session 将控制给定事务作为自己的事务; Session.commit() 将在事务上调用.commit()Session.rollback() 将在事务上调用.rollback()Session.close() 将调用事务上的.rollback。 提示 此使用模式等同于 SQLAlchemy 1.4 处理具有现有 SAVEPOINT 的Connection的方式(即Connection.begin_nested()); Session将完全控制现有的 SAVEPOINT。
  • "rollback_only" - Session仅会接管给定事务的.rollback()调用;.commit()调用不会传播到给定事务。.close()调用不会对给定事务产生影响。 提示 此使用模式等同于 SQLAlchemy 1.4 处理具有现有常规数据库事务的Connection的方式(即Connection.begin());Session将传播Session.rollback()调用到底层事务,但不会传播Session.commit()Session.close()调用。

自 2.0.0rc1 版本新增。

close_resets_only -

默认为True。确定会话在调用.close()后是否应该重置自身,还是应该处于不再可用的状态,禁用重用。

自 2.0.22 版本新增:添加标志close_resets_only。未来的 SQLAlchemy 版本可能会将此标志的默认值更改为False

另请参阅

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

代码语言:javascript复制
method add(instance: object, _warn: bool = True) → None

将一个对象放入此Session中。

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

传递给Session.add()方法时处于分离状态的对象将直接转移到持久化状态。

如果由Session使用的事务被回滚,那些在传递给Session.add()时处于瞬态的对象将会被移回到瞬态状态,并且不再存在于这个Session中。

另请参见

Session.add_all()

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

代码语言:javascript复制
method add_all(instances: Iterable[object]) → None

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

请参阅Session.add()的文档以获取一般行为描述。

另请参见

Session.add()

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

代码语言:javascript复制
method begin(nested: bool = False) → SessionTransaction

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

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

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

参数:

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

返回:

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

另请参见

自动开始

管理事务

Session.begin_nested()

代码语言:javascript复制
method begin_nested() → SessionTransaction

在此Session上开始“嵌套”事务,例如 SAVEPOINT。

目标数据库和相关驱动程序必须支持 SQL SAVEPOINT,以使此方法正常工作。

有关 SAVEPOINT 事务的文档,请参阅 使用 SAVEPOINT。

返回:

SessionTransaction 对象。请注意,SessionTransaction 作为上下文管理器,允许在“with”块中使用 Session.begin_nested()。请参阅 使用 SAVEPOINT 获取使用示例。

另请参阅

使用 SAVEPOINT

可串行化隔离 / Savepoints / 事务性 DDL - 使用 SQLite 驱动程序时,为使 SAVEPOINT 正常工作需要特殊的解决方法。对于 asyncio 案例,请参阅 可串行化隔离 / Savepoints / 事务性 DDL(asyncio 版本) 部分。

代码语言:javascript复制
method bind_mapper(mapper: _EntityBindKey[_O], bind: _SessionBind) → None

Mapper 或任意 Python 类与“bind”关联,例如一个 EngineConnection

给定的实体被添加到 Session.get_bind() 方法使用的查找中。

参数:

  • mapper – 一个 Mapper 对象,或者一个映射类的实例,或者任何作为一组映射类基础的 Python 类。
  • bind – 一个 EngineConnection 对象。

另请参阅

分区策略(例如,每个 Session 多个数据库后端)

Session.binds

Session.bind_table()

代码语言:javascript复制
method bind_table(table: TableClause, bind: Engine | Connection) → None

Table 与“bind”关联,例如一个 EngineConnection

给定的 Table 被添加到 Session.get_bind() 方法使用的查找中。

参数:

  • table – 一个 Table 对象,通常是 ORM 映射的目标,或者存在于可选择的映射中。
  • bind - 一个EngineConnection对象。

另请参阅

分区策略(例如每个 Session 的多个数据库后端)

Session.binds

Session.bind_mapper()

代码语言:javascript复制
method bulk_insert_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]], return_defaults: bool = False, render_nulls: bool = False) → None

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

传统特性

该方法是 SQLAlchemy 2.0 系列的一个传统特性。对于现代的批量插入和更新,请参见 ORM 批量插入语句和 ORM 按主键批量更新部分。2.0 API 共享了与该方法的实现细节,并添加了新的特性。

参数:

  • mapper - 一个映射类,或者实际的Mapper对象,表示映射列表中所代表的单一对象种类。
  • mappings - 一系列字典,每个字典包含要插入的映射行的状态,以映射类上的属性名称表示。如果映射涉及多个表,例如连接继承映射,则每个字典必须包含要填充到所有表中的所有键。
  • return_defaults - 当为 True 时,INSERT 过程将被修改以确保新生成的主键值将被获取。该参数的理由通常是为了使连接表继承映射能够批量插入。 注意 对于不支持 RETURNING 的后端,Session.bulk_insert_mappings.return_defaults参数可能会显著降低性能,因为 INSERT 语句无法再批量处理。有关受影响的后端的背景信息,请参阅 INSERT 语句的“插入多个值”行为。
  • render_nulls - 当为 True 时,None值将导致在 INSERT 语句中包含一个 NULL 值,而不是将列从 INSERT 中省略。这允许所有被 INSERT 的行具有相同的列集,从而允许将完整的行集批量发送到 DBAPI。通常,每个包含与上一行不同的 NULL 值组合的列集必须从渲染的 INSERT 语句中省略不同的列系列,这意味着必须作为单独的语句发出。通过传递此标志,可以确保将完整的行集批量处理为一个批次;但成本是,通过省略列调用的服务器端默认值将被跳过,因此必须注意确保这些不是必需的。 警告 当设置此标志时,不会调用服务器端默认的 SQL 值,对于那些作为 NULL 插入的列;NULL 值将被显式发送。必须注意确保整个操作不需要调用服务器端默认函数。

另请参阅

启用 ORM 的 INSERT、UPDATE 和 DELETE 语句

Session.bulk_save_objects()

Session.bulk_update_mappings()

代码语言:javascript复制
method bulk_save_objects(objects: Iterable[object], return_defaults: bool = False, update_changed_only: bool = True, preserve_order: bool = True) → None

对给定对象列表执行批量保存。

传统功能

该方法是 SQLAlchemy 2.0 系列的传统功能。对于现代的批量 INSERT 和 UPDATE,请参见 ORM 批量 INSERT 语句和 ORM 按主键批量 UPDATE 部分。

对于一般的 INSERT 和 UPDATE 现有 ORM 映射对象,建议使用标准的工作单元数据管理模式,介绍在 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 启用的 INSERT、UPDATE 和 DELETE 语句

Session.bulk_insert_mappings()

Session.bulk_update_mappings()

代码语言:javascript复制
method bulk_update_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]]) → None

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

传统特性

该方法是 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()

代码语言:javascript复制
method close() → None

结束由此 Session 使用的事务资源和 ORM 对象。

这会清除与此 Session 关联的所有 ORM 对象,结束任何正在进行的事务,并释放此 Session 从相关 Engine 对象中检出的任何 Connection 对象。然后,该操作将 Session 置于可以再次使用的状态。

提示

在默认运行模式下,Session.close() 方法不会阻止该 Session 再次使用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

代码语言:javascript复制
classmethod close_all() → None

继承自 sqlalchemy.orm.session._SessionClassMethods.close_all 方法的 sqlalchemy.orm.session._SessionClassMethods

关闭所有内存中的会话。

自版本 1.3 起已弃用:Session.close_all()方法已弃用,将在将来的版本中删除。请参考close_all_sessions()

代码语言:javascript复制
method commit() → None

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

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

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

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

另请参阅

提交

管理事务

在使用 AsyncSession 时避免隐式 IO

代码语言:javascript复制
method connection(bind_arguments: _BindArguments | None = None, execution_options: CoreExecuteOptionsParameter | None = None) → Connection

返回一个与该Session对象的事务状态对应的Connection对象。

返回当前事务对应的 Connection,或者如果没有进行中的事务,则开始新的事务并返回 Connection(请注意,在第一个 SQL 语句被发出之前,与 DBAPI 之间不会建立事务状态)。

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

参数:

  • bind_arguments – 绑定参数字典。可能包括“mapper”,“bind”,“clause”等其他传递给 Session.get_bind() 的自定义参数。
  • execution_options – 一个执行选项字典,当首次获得连接时将传递给 Connection.execution_options()。如果连接已经存在于 Session 中,将发出警告并忽略参数。 另请参阅 设置事务隔离级别 / DBAPI AUTOCOMMIT
代码语言:javascript复制
method delete(instance: object) → None

将实例标记为已删除。

假设传入的对象在调用该方法后处于 持久化 或 分离 状态;在此方法被调用后,对象将保持 持久化 状态,直到下一次刷新操作进行。在此期间,该对象也将是 Session.deleted 集合的成员。

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

另请参阅

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

代码语言:javascript复制
attribute deleted

所有在此 Session 中标记为 ‘deleted’ 的实例集合。

代码语言:javascript复制
attribute dirty

所有被认为是脏的持久化实例集合。

例如:

代码语言:javascript复制
some_mapped_object in session.dirty

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

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

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

代码语言:javascript复制
method enable_relationship_loading(obj: object) → None

将对象与此Session关联以进行相关对象加载。

警告

enable_relationship_loading()存在以服务于特殊用例,并不建议用于一般用途。

使用relationship()映射的属性的访问将尝试使用此Session作为连接源从数据库加载值。值将根据此对象上存在的外键和主键值加载 - 如果不存在,则这些关系将不可用。

对象将附加到此会话,但不会参与任何持久性操作;它的状态对于几乎所有目的都将保持“瞬态”或“分离”,除了关系加载的情况。

还要注意,反向引用通常不会按预期工作。如果目标对象上的关系绑定属性发生更改,则可能不会触发反向引用事件,如果有效值已从保存外键值的值中加载,则不会触发事件。

Session.enable_relationship_loading()方法类似于relationship()上的load_on_pending标志。与该标志不同,Session.enable_relationship_loading()允许对象保持瞬态,同时仍然能够加载相关项目。

要使一个临时对象与Session相关联,可以通过Session.enable_relationship_loading()将其添加到Session中。如果该对象代表数据库中现有的标识,则应使用Session.merge()进行合并。

当 ORM 正常使用时,Session.enable_relationship_loading()不会改善行为 - 对象引用应该在对象级别而不是在外键级别构建,以便它们在 flush()继续之前以普通方式存在。此方法不适用于一般用途。

另请参见

relationship.load_on_pending - 此标志允许在待处理项目上对多对一进行每关系加载。

make_transient_to_detached() - 允许将对象添加到Session中而不发出 SQL,然后在访��时取消过期属性。

代码语言:javascript复制
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 表达式构造。

返回一个代表语句执行结果的Result对象。

例如:

代码语言:javascript复制
from sqlalchemy import select
result = session.execute(
    select(User).where(User.id == 5)
)

Session.execute()的 API 契约类似于Connection.execute()的契约,是Connection的 2.0 风格版本。

从版本 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对象。

代码语言:javascript复制
method expire(instance: object, attribute_names: Iterable[str] | None = None) → None

使实例上的属性过期。

标记实例的属性为过期。下次访问过期属性时,将向Session对象的当前事务上下文发出查询,以加载给定实例的所有过期属性。请注意,高度隔离的事务将返回与该事务中先前读取的相同值,而不管该事务外的数据库状态发生了什么变化。

要同时使Session中的所有对象过期,请使用Session.expire_all()

当调用Session.rollback()Session.commit()方法时,Session对象的默认行为是使所有状态过期,以便为新事务加载新状态。因此,仅在当前事务中发出非 ORM SQL 语句的特定情况下调用Session.expire()才有意义。

参数:

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

另请参阅

刷新/过期 - 入门材料

Session.expire()

Session.refresh()

Query.populate_existing()

代码语言:javascript复制
method expire_all() → None

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

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

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

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

另请参阅

刷新 / 过期 - 入门材料

Session.expire()

Session.refresh()

Query.populate_existing()

代码语言:javascript复制
method expunge(instance: object) → None

从这个Session中移除实例。

这将释放对该实例的所有内部引用。根据expunge级联规则将应用级联。

代码语言:javascript复制
method expunge_all() → None

从这个Session中移除所有对象实例。

这相当于在这个Session中调用expunge(obj)来移除所有对象。

代码语言:javascript复制
method flush(objects: Sequence[Any] | None = None) → None

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

将所有待定的对象创建、删除和修改写入数据库,作为 INSERT、DELETE、UPDATE 等操作。操作会自动按照会话的工作单元依赖解决器进行排序。

数据库操作将在当前事务上下文中发出,并且不会影响事务的状态,除非发生错误,此时整个事务都会回滚。在事务中随时可以刷新(flush())以将更改从 Python 移动到数据库的事务缓冲区。

参数:

对象

可选;限制刷新操作仅对给定集合中存在的元素进行操作。

这个功能适用于极少数情况,特定对象可能需要在完全刷新(flush())之前进行操作。它不适用于一般用途。

代码语言:javascript复制
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

例如:

代码语言:javascript复制
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”,调用如下所示:

代码语言:javascript复制
my_object = session.get(SomeClass, 5)

元组形式包含主键值,通常按照它们与映射的Table对象的主键列对应的顺序排列,或者如果使用了Mapper.primary_key配置参数,则按照该参数的顺序排列。例如,如果行的主键由整数数字“5,10”表示,则调用如下所示:

代码语言:javascript复制
my_object = session.get(SomeClass, (5, 10))

字典形式应包含作为主键每个元素相应的映射属性名称的键。如果映射类具有存储对象主键值的属性idversion_id,则调用如下所示:

代码语言:javascript复制
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

代码语言:javascript复制
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”。

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

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

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

解析顺序为:

  1. 如果给定了mapper并且Session.binds存在,则首先基于正在使用的映射器,然后基于正在使用的映射类,然后基于映射类的__mro__中存在的任何基类,从更具体的超类到更一般的类来定位一个绑定。
  2. 如果给定了条件并且Session.binds存在,则基于Session.binds中的给定条件中找到的Table对象定位绑定。
  3. 如果Session.binds存在,则返回该绑定。
  4. 如果给定了条件,则尝试返回与该条件最终关联的MetaData绑定。
  5. 如果提供了映射器,尝试返回与最终与该映射器映射的Table或其他可选择对象关联的MetaData绑定。
  6. 如果找不到绑定,则会引发UnboundExecutionError

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

参数:

  • mapper – 可选的映射类或相应的Mapper实例。绑定可以首先从此Session关联的“绑定”映射中派生,其次是从该Mapper映射到的Table关联的MetaData中派生。
  • clause – 一个ClauseElement(即select()text()等)。如果mapper参数不存在或无法生成绑定,则将搜索给定的表达式构造,通常是与绑定的MetaData关联的Table

另请参阅

分区策略(例如每个会话的多个数据库后端)

Session.binds

Session.bind_mapper()

Session.bind_table()

代码语言:javascript复制
method get_nested_transaction() → SessionTransaction | None

返回正在进行的当前嵌套事务(如果有)。

新版本 1.4 中新增。

代码语言:javascript复制
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

根据给定的主键标识符返回精确的一个实例,如果未找到则引发异常。

如果查询未选择任何行,则引发sqlalchemy.orm.exc.NoResultFound

有关参数的详细文档,请参阅方法Session.get()

新版本 2.0.22 中新增。

返回:

对象实例。

另请参见

Session.get() - 相当的方法,代替

如果未找到具有提供的主键的行,则返回None

代码语言:javascript复制
method get_transaction() → SessionTransaction | None

返回正在进行的当前根事务(如果有)。

新版本 1.4 中新增。

代码语言:javascript复制
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]

继承自 sqlalchemy.orm.session._SessionClassMethods.identity_key 的方法 sqlalchemy.orm.session._SessionClassMethods

返回一个标识键。

这是 identity_key() 的别名。

代码语言:javascript复制
attribute identity_map: IdentityMap

对象标识到对象本身的映射。

通过Session.identity_map.values()迭代提供对当前会话中当前持久对象(即具有行标识的对象)的完整集合的访问。

另请参见

identity_key() - 辅助函数,用于生成此字典中使用的键。

代码语言:javascript复制
method in_nested_transaction() → bool

如果此 Session 已开始嵌套事务(例如,SAVEPOINT),则返回 True。

新版本 1.4 中新增。

代码语言:javascript复制
method in_transaction() → bool

如果此 Session 已开始事务,则返回 True。

新版本 1.4 中新增。

另请参见

Session.is_active

代码语言:javascript复制
attribute info

一个用户可修改的字典。

此字典的初始值可以使用 info 参数来填充到 Session 构造函数或 sessionmaker 构造函数或工厂方法中。此处的字典始终局限于此 Session 并且可以独立于所有其他 Session 对象进行修改。

代码语言:javascript复制
method invalidate() → None

关闭此会话,使用连接失效。

这是 Session.close() 的变体,还将确保对每个当前用于事务的 Connection 对象调用 Connection.invalidate() 方法(通常只有一个连接,除非 Session 与多个引擎一起使用)。

当已知数据库处于不再安全使用连接的状态时,可以调用此方法。

以下示例说明了在使用 gevent 时可能出现的可导致底层连接应被丢弃的 Timeout 异常情况:

代码语言:javascript复制
import gevent

try:
    sess = Session()
    sess.add(User())
    sess.commit()
except gevent.Timeout:
    sess.invalidate()
    raise
except:
    sess.rollback()
    raise

此方法还会执行 Session.close() 所做的所有操作,包括清除所有 ORM 对象。

代码语言:javascript复制
attribute is_active

如果此 Session 未处于“部分回滚”状态,则返回 True。

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

“部分回滚”状态通常表示 Session 的刷新过程失败,并且必须发出 Session.rollback() 方法以完全回滚事务。

如果此 Session 未处于事务中,则当首次使用时,Session 将自动开始,因此在这种情况下,Session.is_active 将返回 True。

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

另请参阅

“由于刷新期间的先前异常,此会话的事务已回滚。”(或类似内容)

Session.in_transaction()

代码语言:javascript复制
method is_modified(instance: object, include_collections: bool = True) → bool

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

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

实际上,这是检查 Session.dirty 集合中给定实例的更昂贵和准确的版本;对每个属性的净“脏”状态进行全面测试。

例如:

代码语言:javascript复制
return session.is_modified(someobject)

这种方法有一些注意事项:

  • Session.dirty 集合中存在的实例在使用此方法进行测试时可能会报告 False。这是因为对象可能通过属性突变接收到更改事件,从而将其置于 Session.dirty 中,但最终状态与从数据库加载的状态相同,在这里没有净更改。
  • 当新值被应用时,标量属性可能没有记录先前设置的值,如果在接收新值时该属性未加载或已过期,则假定该属性有一个更改,即使最终对其数据库值没有净更改也是如此。在这些情况下,即使最终没有针对数据库值的净更改,也假定该属性有一个更改。在大多数情况下,当发生 set 事件时,SQLAlchemy 不需要“旧”值,因此如果旧值不存在,则跳过 SQL 调用的开销,这是基于标量值通常需要 UPDATE 的假设,并且在那几种情况下它不需要的情况下,平均比发出防御性的 SELECT 更便宜。 仅当属性容器的 active_history 标志设置为 True 时,才无条件地在 set 时获取“旧”值。这个标志通常设置为主键属性和不是简单多对一的标量对象引用。要为任意映射列设置此标志,请使用 column_property()active_history 参数。

参数:

  • instance – 被测试的映射实例。
  • include_collections – 表示是否应包含多值集合在操作中。将其设置为 False 是一种检测仅基于本地列的属性(即标量列或多对一外键),这些属性会导致此实例在刷新时进行 UPDATE 的方法。
代码语言:javascript复制
method merge(instance: _O, *, load: bool = True, options: Sequence[ORMOption] | None = None) → _O

将给定实例的状态复制到此 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中的替代方法

代码语言:javascript复制
attribute new

在此Session中标记为“new”的所有实例的集合。

代码语言:javascript复制
attribute no_autoflush

返回一个禁用自动刷新的上下文管理器。

例如:

代码语言:javascript复制
with session.no_autoflush:

    some_object = SomeClass()
    session.add(some_object)
    # won't autoflush
    some_object.related_thing = session.query(SomeRelated).first()

with: 块内进行的操作不会受到在查询访问时发生的刷新的影响。当初始化一系列涉及现有数据库查询的对象时,尚未完成的对象不应立即被刷新时,这是有用的。

代码语言:javascript复制
classmethod object_session(instance: object) → Session | None

继承自 sqlalchemy.orm.session._SessionClassMethods.object_session 方法的 sqlalchemy.orm.session._SessionClassMethods

返回一个对象所属的 Session

这是 object_session() 的别名。

代码语言:javascript复制
method prepare() → None

准备当前进行中的事务以进行两阶段提交。

如果没有进行事务,则此方法会引发一个 InvalidRequestError

仅两阶段会话的根事务可以被准备。如果当前事务不是这样的事务,则会引发一个 InvalidRequestError

代码语言:javascript复制
method query(*entities: _ColumnsClauseArgument[Any], **kwargs: Any) → Query[Any]

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

请注意,Query 对象自 SQLAlchemy 2.0 起已被视为遗留;现在使用 select() 构造 ORM 查询。

另请参阅

SQLAlchemy 统一教程

ORM 查询指南

遗留查询 API - 遗留 API 文档

代码语言:javascript复制
method refresh(instance: object, attribute_names: Iterable[str] | None = None, with_for_update: ForUpdateParameter = None) → None

使给定实例的属性过期并刷新。

首先将选定的属性作为当使用 Session.expire() 时会过期的那样进行过期处理;然后将发出 SELECT 语句到数据库,以使用当前事务中可用的当前值刷新基于列的属性。

如果对象已经被急切加载,那么 relationship() 定向属性也将立即被加载,使用它们最初加载时使用的急切加载策略。

版本 1.4 中的新功能:- Session.refresh() 方法也可以刷新急切加载的属性。

relationship() 导向属性通常会使用 select(或“延迟加载”)加载策略,如果它们在 attribute_names 集合中被明确命名,也会加载**,使用 immediate 加载策略对属性发出 SELECT 语句。如果惰性加载的关系未在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,或者可能是一个包含标志的字典,用于指示更具体的 FOR UPDATE 标志集合用于 SELECT;标志应该与 Query.with_for_update() 的参数匹配。取代Session.refresh.lockmode 参数。

另请参阅

刷新/过期 - 初级材料

Session.expire()

Session.expire_all()

填充现有对象 - 允许任何 ORM 查询刷新对象,就像它们通常加载的那样。

代码语言:javascript复制
method reset() → None

关闭此Session使用的事务资源和 ORM 对象,将会话重置为其初始状态。

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

新版本 2.0.22。

另请参阅

关闭 - 详细介绍了 Session.close()Session.reset() 的语义。

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

代码语言:javascript复制
method rollback() → None

回滚当前进行中的事务。

如果没有进行中的事务,则此方法是一个直通方法。

该方法始终回滚最顶层的数据库事务,丢弃可能正在进行的任何嵌套事务。

另请参阅

回滚

事务管理

代码语言:javascript复制
method scalar(statement: Executable, params: _CoreSingleExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) → Any

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

用法和参数与Session.execute()相同;返回结果是一个标量 Python 值。

代码语言:javascript复制
method scalars(statement: Executable, params: _CoreAnyExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) → ScalarResult[Any]

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

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

返回:

一个ScalarResult对象

新版本 1.4.24 中添加:Session.scalars()

新版本 1.4.26 中添加:scoped_session.scalars()

另请参阅

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

代码语言:javascript复制
class sqlalchemy.orm.SessionTransaction

一个 Session 级别的事务。

SessionTransaction 是由 Session.begin()Session.begin_nested() 方法生成的。它在现代用法中主要是一个内部对象,为会话事务提供上下文管理器。

SessionTransaction 交互的文档位于:管理事务。

自版本 1.4 更改:直接处理 SessionTransaction 对象的范围和 API 方法已经简化。

另请参阅

管理事务

Session.begin()

Session.begin_nested()

Session.rollback()

Session.commit()

Session.in_transaction()

Session.in_nested_transaction()

Session.get_transaction()

Session.get_nested_transaction()

成员

嵌套, 原始, 父级

类签名

sqlalchemy.orm.SessionTransaction (sqlalchemy.orm.state_changes._StateChange, sqlalchemy.engine.util.TransactionalContext)

代码语言:javascript复制
attribute nested: bool = False

指示这是否为嵌套或 SAVEPOINT 事务。

SessionTransaction.nested 为 True 时,预计 SessionTransaction.parent 也会出现,链接到封闭的 SessionTransaction

另请参见

SessionTransaction.origin

代码语言:javascript复制
attribute origin: SessionTransactionOrigin

SessionTransaction 的来源。

指的是一个 SessionTransactionOrigin 实例,该实例是指导致构造此 SessionTransaction 的源事件的枚举。

新版本 2.0 中添加。

代码语言:javascript复制
attribute parent

SessionTransaction 的父级 SessionTransaction

如果此属性为 None,表示此 SessionTransaction 位于堆栈顶部,并且对应于真实的 “COMMIT”/”ROLLBACK” 块。如果非 None,则这是一个 “子事务”(由刷新进程使用的内部标记对象)或 “嵌套” / SAVEPOINT 事务。如果 SessionTransaction.nested 属性为 True,则这是一个 SAVEPOINT,如果为 False,表示这是一个子事务。

代码语言:javascript复制
class sqlalchemy.orm.SessionTransactionOrigin

表示SessionTransaction的来源。

此枚举存在于任何 SessionTransaction 对象的 SessionTransaction.origin 属性上。

新版本 2.0 中添加。

成员

AUTOBEGIN, BEGIN, BEGIN_NESTED, SUBTRANSACTION

类签名

sqlalchemy.orm.SessionTransactionOrigin (enum.Enum)

代码语言:javascript复制
attribute AUTOBEGIN = 0

通过自动开始开始的事务

代码语言:javascript复制
attribute BEGIN = 1

通过调用 Session.begin() 开始事务。

代码语言:javascript复制
attribute BEGIN_NESTED = 2

通过 Session.begin_nested() 开始事务。

代码语言:javascript复制
attribute SUBTRANSACTION = 3

事务是内部的 “子事务”

会话工具

对象名称

描述

close_all_sessions()

关闭内存中的所有会话。

make_transient(instance)

修改给定实例的状态,使其为瞬态。

make_transient_to_detached(instance)

使给定的瞬态实例成为脱离的。

object_session(instance)

返回给定实例所属的 Session。

was_deleted(object_)

如果给定对象在会话刷新中被删除,则返回 True。

代码语言:javascript复制
function sqlalchemy.orm.close_all_sessions() → None

关闭内存中的所有会话。

此函数会查询所有 Session 对象的全局注册表,并对它们调用 Session.close() ,将它们重置为干净的状态。

此函数不适用于一般用途,但在拆卸方案中的测试套件中可能有用。

版本 1.3 中的新功能。

代码语言:javascript复制
function sqlalchemy.orm.make_transient(instance: object) → None

改变给定实例的状态,使其成为瞬态的。

注意

make_transient() 是仅用于高级用例的特殊情况函数。

假定给定的映射实例处于持久的或脱离的状态。 该函数将删除其与任何 Session 的关联以及其 InstanceState.identity。 其效果是对象将表现得像它是新构造的,除了保留在调用时加载的任何属性/集合值。 如果此对象已因使用 Session.delete() 而被删除,则还将重置 InstanceState.deleted 标志。

警告

make_transient() “取消过期”或以其他方式急切加载目前未加载的 ORM 映射属性。 这包括:

  • 通过 Session.expire() 过期
  • 由于提交会话事务的自然效果,会话过期,例如 Session.commit()
  • 通常是惰性加载,但目前未加载
  • 是“延迟加载”(参见 限制哪些列与列延迟加载)并且尚未加载
  • 在加载此对象的查询中不存在,例如,在连接表继承和其他场景中常见的情况下。

在调用make_transient()之后,通常会解析为None的未加载属性,例如上面的属性,或者是针对集合导向属性的空集合。 由于对象是临时的,并且与任何数据库标识都没有关联,因此将不再检索这些值。

另请参阅

make_transient_to_detached()

代码语言:javascript复制
function sqlalchemy.orm.make_transient_to_detached(instance: object) → None

使给定的临时实例脱离。

注意

make_transient_to_detached()是一个仅用于高级用例的特殊情况函数。

给定实例的所有属性历史记录都将被重置,就好像该实例是从查询中新加载的一样。 缺少的属性将被标记为过期。 对象的主键属性将被制成实例的“键”,这些主键属性是必需的。

然后可以将对象添加到会话中,或者可能与 load=False 标志合并,此时它看起来就像是以这种方式加载的,而不会发出 SQL。

这是一个特殊的用例函数,它与对Session.merge()的普通调用不同,因为可以在不进行任何 SQL 调用的情况下制造给定的持久状态。

另请参阅

make_transient()

Session.enable_relationship_loading()

代码语言:javascript复制
function sqlalchemy.orm.object_session(instance: object) → Session | None

返回给定实例所属的Session

这基本上与InstanceState.session访问器相同。 有关详细信息,请参阅该属性。

代码语言:javascript复制
function sqlalchemy.orm.util.was_deleted(object_: object) → bool

如果给定对象在会话刷新时被删除,则返回 True。

无论对象是否持久还是分离,都是如此。

另请参阅

InstanceState.was_deleted

属性和状态管理工具

这些函数由 SQLAlchemy 属性检测 API 提供,用于提供详细的接口来处理实例、属性值和历史记录。 在构建事件监听器函数时,其中一些函数非常有用,例如在 ORM 事件中描述的函数。

对象名称

描述

del_attribute(instance, key)

删除属性的值,并触发历史事件。

flag_dirty(instance)

标记一个实例为“脏”,而不具体提到任何属性。

flag_modified(instance, key)

将实例上的属性标记为“修改”。

get_attribute(instance, key)

获取属性的值,触发任何所需的可调用对象。

get_history(obj, key[, passive])

为给定对象和属性键返回一个History 记录。

History

添加、未更改和已删除值的三元组,表示在工具化属性上发生的更改。

init_collection(obj, key)

初始化集合属性并返回集合适配器。

instance_state

返回给定映射对象的InstanceState。

is_instrumented(instance, key)

如果给定实例的给定属性由 attributes 包进行了工具化,则返回 True。

object_state(instance)

给定一个对象,返回与该对象关联的InstanceState。

set_attribute(instance, key, value[, initiator])

设置属性的值,触发历史事件。

set_committed_value(instance, key, value)

设置属性的值,没有历史事件。

代码语言:javascript复制
function sqlalchemy.orm.util.object_state(instance: _T) → InstanceState[_T]

给定一个对象,返回与该对象关联的InstanceState

如果没有配置映射,则会引发sqlalchemy.orm.exc.UnmappedInstanceError

通过 inspect() 函数可以获得等效功能,如下所示:

代码语言:javascript复制
inspect(instance)

使用检查系统将会在实例不属于映射的情况下引发sqlalchemy.exc.NoInspectionAvailable

代码语言:javascript复制
function sqlalchemy.orm.attributes.del_attribute(instance: object, key: str) → None

删除属性的值,触发历史事件。

无论直接应用于类的工具化如何,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来建立由 SQLAlchemy 理解的属性状态。

代码语言:javascript复制
function sqlalchemy.orm.attributes.get_attribute(instance: object, key: str) → Any

获取属性的值,触发任何所需的可调用对象。

无论直接应用于类的仪器是什么,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来使用 SQLAlchemy 理解的属性状态。

代码语言:javascript复制
function sqlalchemy.orm.attributes.get_history(obj: object, key: str, passive: PassiveFlag = symbol('PASSIVE_OFF')) → History

返回给定对象和属性键的History记录。

这是给定属性的预刷新历史记录,每次Session刷新对当前数据库事务进行更改时都会重置。

注意

优先使用AttributeState.historyAttributeState.load_history()访问器来检索实例属性的History

参数:

  • obj - 其类由属性包装的对象。
  • key - 字符串属性名称。
  • passive - 如果值尚不存在,则指示属性的加载行为。这是一个比特标志属性,默认为符号PASSIVE_OFF,表示应发出所有必要的 SQL。

另请参阅

AttributeState.history

AttributeState.load_history() - 如果值未在本地存在,则使用加载器可调用检索历史记录。

代码语言:javascript复制
function sqlalchemy.orm.attributes.init_collection(obj: object, key: str) → CollectionAdapter

初始化集合属性并返回集合适配器。

此函数用于为先前未加载的属性提供直接访问集合内部。例如:

代码语言:javascript复制
collection_adapter = init_collection(someobject, 'elements')
for elem in values:
    collection_adapter.append_without_event(elem)

要更轻松地执行上述操作,请参见set_committed_value()

参数:

  • obj - 一个映射对象
  • key - 集合所在的字符串属性名称。
代码语言:javascript复制
function sqlalchemy.orm.attributes.flag_modified(instance: object, key: str) → None

将实例上的属性标记为“修改”。

这将在实例上设置“修改”标志,并为给定属性建立一个无条件的更改事件。属性必须有一个值存在,否则会引发InvalidRequestError

要将对象标记为“脏”,而不引用任何特定属性,以便在刷新时将其视为“脏”,请使用flag_dirty()调用。

另请参阅

flag_dirty()

代码语言:javascript复制
function sqlalchemy.orm.attributes.flag_dirty(instance: object) → None

将实例标记为“脏”,而不提及任何特定属性。

这是一个特殊操作,将允许对象通过刷新过程,以便被SessionEvents.before_flush()等事件拦截。请注意,对于没有更改的对象,在刷新过程中不会发出任何 SQL,即使通过此方法标记为脏。但是,SessionEvents.before_flush()处理程序将能够在Session.dirty集合中看到对象,并可能对其进行更改,然后将其包含在发出的 SQL 中。

版本 1.2 中的新功能。

另请参阅

flag_modified()

代码语言:javascript复制
function sqlalchemy.orm.attributes.instance_state()

返回给定映射对象的InstanceState

此函数是object_state()的内部版本。在这里,建议使用object_state()和/或inspect()函数,因为它们会在给定对象未映射时分别发出信息性异常。

代码语言:javascript复制
function sqlalchemy.orm.instrumentation.is_instrumented(instance, key)

如果给定实例上的给定属性由属性包进行了仪器化,则返回 True。

无论直接应用于类的仪器化如何,都可以使用此函数,即不需要描述符。

代码语言:javascript复制
function sqlalchemy.orm.attributes.set_attribute(instance: object, key: str, value: Any, initiator: AttributeEventToken | None = None) → None

设置属性的值,触发历史事件。

无论直接应用于类的仪器化如何,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来建立 SQLAlchemy 理解的属性状态。

参数:

  • instance – 将被修改的对象
  • key – 属性的字符串名称
  • value – 要分配的值
  • initiator – 一个Event的实例,可能已从先前的事件侦听器传播。当在现有事件侦听函数中使用set_attribute()函数时,会使用此参数;该对象可用于跟踪事件链的起源。 版本 1.2.3 中的新功能。
代码语言:javascript复制
function sqlalchemy.orm.attributes.set_committed_value(instance, key, value)

设置没有历史事件的属性的值。

取消任何先前存在的历史。对于持有标量属性的属性,值应为标量值,对于任何持有集合属性的属性,值应为可迭代对象。

当惰性加载程序触发并从数据库加载附加数据时,使用的是相同的基础方法。特别是,此方法可被应用代码使用,通过单独的查询加载了额外的属性或集合,然后将其附加到实例,就好像它是其原始加载状态的一部分。

代码语言:javascript复制
class sqlalchemy.orm.attributes.History

一个由添加、未更改和删除值组成的 3 元组,表示在受监控属性上发生的更改。

获取对象上特定属性的History对象的最简单方法是使用inspect()函数:

代码语言:javascript复制
from sqlalchemy import inspect

hist = inspect(myobject).attrs.myattribute.history

每个元组成员都是一个可迭代序列:

  • added - 添加到属性中的项目集合(第一个元组元素)。
  • unchanged - 未更改属性上的项目集合(第二个元组元素)。
  • deleted - 从属性中删除的项目集合(第三个元组元素)。

成员

added, deleted, empty(), has_changes(), non_added(), non_deleted(), sum(), unchanged

类签名

sqlalchemy.orm.Historybuiltins.tuple

代码语言:javascript复制
attribute added: Tuple[()] | List[Any]

字段 0 的别名

代码语言:javascript复制
attribute deleted: Tuple[()] | List[Any]

字段 2 的别名

代码语言:javascript复制
method empty() → bool

如果此History没有更改和现有的未更改状态,则返回 True。

代码语言:javascript复制
method has_changes() → bool

如果此History有更改,则返回 True。

代码语言:javascript复制
method non_added() → Sequence[Any]

返回一个未更改 删除的集合。

代码语言:javascript复制
method non_deleted() → Sequence[Any]

返回一个添加 未更改的集合。

代码语言:javascript复制
method sum() → Sequence[Any]

返回一个添加 未更改 删除的集合。

代码语言:javascript复制
attribute unchanged: Tuple[()] | List[Any]

字段 1 的别名

Session 和 sessionmaker()

对象名称

描述

ORMExecuteState

表示对Session.execute()方法的调用,作为传递给SessionEvents.do_orm_execute()事件钩子。

Session

管理 ORM 映射对象的持久性操作。

sessionmaker

一个可配置的Session工厂。

SessionTransaction

一个Session级事务。

SessionTransactionOrigin

表示SessionTransaction的来源。

代码语言:javascript复制
class sqlalchemy.orm.sessionmaker

可配置的Session工厂。

当调用sessionmaker工厂时,会根据此处设定的配置参数生成新的Session对象。

例如:

代码语言:javascript复制
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# an Engine, which the Session will use for connection
# resources
engine = create_engine('postgresql psycopg2://scott:tiger@localhost/')

Session = sessionmaker(engine)

with Session() as session:
    session.add(some_object)
    session.add(some_other_object)
    session.commit()

上下文管理器的使用是可选的;否则,返回的Session对象可以通过Session.close()方法显式关闭。使用try:/finally:块是可选的,但是会确保即使出现数据库错误也会执行关闭操作:

代码语言:javascript复制
session = Session()
try:
    session.add(some_object)
    session.add(some_other_object)
    session.commit()
finally:
    session.close()

sessionmaker的作用类似于EngineConnection对象的工厂。通过这种方式,它还包括一个sessionmaker.begin()方法,提供一个上下文管理器,既开始又提交事务,并在完成时关闭Session,如果发生任何错误则回滚事务:

代码语言:javascript复制
Session = sessionmaker(engine)

with Session.begin() as session:
    session.add(some_object)
    session.add(some_other_object)
# commits transaction, closes session

1.4 版本中新增。

当调用sessionmaker构造Session时,也可以传递关键字参数给该方法;这些参数将覆盖全局配置的参数。下面我们使用一个绑定到特定Enginesessionmaker来生成一个与该引擎提供的特定Connection绑定的Session

代码语言:javascript复制
Session = sessionmaker(engine)

# bind an individual session to a connection

with engine.connect() as connection:
    with Session(bind=connection) as session:
        # work with session

该类还包括一个sessionmaker.configure() 方法,该方法可用于指定工厂的额外关键字参数,这些参数将对后续生成的Session 对象生效。通常用于在首次使用之前将一个或多个Engine 对象与现有的sessionmaker 工厂关联起来:

代码语言:javascript复制
# application starts, sessionmaker does not have
# an engine bound yet
Session = sessionmaker()

# ... later, when an engine URL is read from a configuration
# file or other events allow the engine to be created
engine = create_engine('sqlite:///foo.db')
Session.configure(bind=engine)

sess = Session()
# work with session

另请参阅

打开和关闭会话 - 使用sessionmaker 创建会话的简介文本。

成员

call(), init(), begin(), close_all(), configure(), identity_key(), object_session()

类签名

sqlalchemy.orm.sessionmaker (sqlalchemy.orm.session._SessionClassMethods, typing.Generic)

代码语言:javascript复制
method __call__(**local_kw: Any) → _S

使用此sessionmaker 中建立的配置生成新的Session 对象。

在 Python 中,当对象“调用”方式与函数相同时,将调用对象上的__call__方法:

代码语言:javascript复制
Session = sessionmaker(some_engine)
session = Session()  # invokes sessionmaker.__call__()
代码语言:javascript复制
method __init__(bind: Optional[_SessionBind] = None, *, class_: Type[_S] = <class 'sqlalchemy.orm.session.Session'>, autoflush: bool = True, expire_on_commit: bool = True, info: Optional[_InfoType] = None, **kw: Any)

构造一个新的sessionmaker

这里的所有参数,除了class_,都对应于直接由Session 接受的参数。有关参数的更多详细信息,请参阅Session.__init__() 文档字符串。

参数:

  • bind – 与新创建的Session 对象关联的Engine 或其他 Connectable
  • class_ – 用于创建新的Session 对象的类。默认为Session
  • autoflush – 与新创建的Session 对象一起使用的自动刷新设置。 另请参阅 刷新 - 关于自动刷新的额外背景信息
  • expire_on_commit=True – 与新创建的Session 对象一起使用的Session.expire_on_commit 设置。
  • info – 可选字典,可以通过Session.info访问。请注意,当info参数被指定给特定的Session构造操作时,此字典会被更新而不是被替换。
  • **kw – 所有其他关键字参数都将传递给新创建的Session对象的构造函数。
代码语言:javascript复制
method begin() → AbstractContextManager[_S]

生成一个上下文管理器,既提供一个新的Session又提供一个提交的事务。

例如:

代码语言:javascript复制
Session = sessionmaker(some_engine)

with Session.begin() as session:
    session.add(some_object)

# commits transaction, closes session

自版本 1.4 起新增。

代码语言:javascript复制
classmethod close_all() → None

继承自 sqlalchemy.orm.session._SessionClassMethods.close_all 方法的 sqlalchemy.orm.session._SessionClassMethods

关闭所有内存中的会话。

自版本 1.3 起弃用:Session.close_all()方法已弃用,将在将来的版本中删除。请参考close_all_sessions()

代码语言:javascript复制
method configure(**new_kw: Any) → None

(重新)配置此 sessionmaker 的参数。

例如:

代码语言:javascript复制
Session = sessionmaker()

Session.configure(bind=create_engine('sqlite://'))
代码语言:javascript复制
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]

继承自 sqlalchemy.orm.session._SessionClassMethods.identity_key 方法的 sqlalchemy.orm.session._SessionClassMethods

返回一个标识键。

这是identity_key()的别名。

代码语言:javascript复制
classmethod object_session(instance: object) → Session | None

继承自 sqlalchemy.orm.session._SessionClassMethods.object_session 方法的 sqlalchemy.orm.session._SessionClassMethods

返回对象所属的Session

这是object_session()的别名。

代码语言:javascript复制
class sqlalchemy.orm.ORMExecuteState

表示对Session.execute()方法的调用,如传递给SessionEvents.do_orm_execute()事件挂钩。

自版本 1.4 起新增。

另请参见

执行事件 - 如何使用SessionEvents.do_orm_execute()的顶级文档

成员

init(), all_mappers, bind_arguments, bind_mapper, execution_options, invoke_statement(), is_column_load, is_delete, is_executemany, is_from_statement, is_insert, is_orm_statement, is_relationship_load, is_select, is_update, lazy_loaded_from, load_options, loader_strategy_path, local_execution_options, parameters, session, statement, update_delete_options, update_execution_options(), user_defined_options

类签名

sqlalchemy.orm.ORMExecuteState (sqlalchemy.util.langhelpers.MemoizedSlots)

代码语言:javascript复制
method __init__(session: Session, statement: Executable, parameters: _CoreAnyExecuteParams | None, execution_options: _ExecuteOptions, bind_arguments: _BindArguments, compile_state_cls: Type[ORMCompileState] | None, events_todo: List[_InstanceLevelDispatch[Session]])

构造一个新的ORMExecuteState

此对象在内部构造。

代码语言:javascript复制
attribute all_mappers

返回一个包含此语句顶层涉及的所有Mapper对象的序列。

所谓“顶层”是指那些在select()查询的结果集行中表示的Mapper对象,或者对于update()delete()查询,即 UPDATE 或 DELETE 的主要主题的映射器。

版本 1.4.0b2 中的新内容。

另请参阅

ORMExecuteState.bind_mapper

代码语言:javascript复制
attribute bind_arguments: _BindArguments

作为Session.execute.bind_arguments字典传递的字典。

此字典可供Session的扩展使用,以传递将帮助确定在一组数据库连接中应使用哪一个来调用此语句的参数。

代码语言:javascript复制
attribute bind_mapper

返回主要的“bind”映射器Mapper

对于调用 ORM 语句的ORMExecuteState对象,即ORMExecuteState.is_orm_statement属性为True,此属性将返回被认为是语句的“主要”映射器的Mapper。术语“bind mapper”指的是Session对象可能被“绑定”到多个映射类键到映射类的多个Engine对象,并且“bind mapper”确定哪些Engine对象将被选择。

对于针对单个映射类调用的语句,ORMExecuteState.bind_mapper 旨在是一种可靠的方式来获取此映射器。

版本 1.4.0b2 中的新功能。

另请参阅

ORMExecuteState.all_mappers

代码语言:javascript复制
attribute execution_options: _ExecuteOptions

当前执行选项的完整字典。

这是语句级选项与本地传递的执行选项的合并。

另请参阅

ORMExecuteState.local_execution_options

Executable.execution_options()

ORM 执行选项

代码语言:javascript复制
method invoke_statement(statement: Executable | None = None, params: _CoreAnyExecuteParams | None = None, execution_options: OrmExecuteOptionsParameter | None = None, bind_arguments: _BindArguments | None = None) → Result[Any]

执行由此ORMExecuteState表示的语句,而不重新调用已经进行的事件。

该方法实质上执行当前语句的可重入执行,当前正在调用SessionEvents.do_orm_execute()事件。这样做的用例是为了事件处理程序想要覆盖最终Result对象返回方式,比如从离线缓存中检索结果或者从多次执行中连接结果的方案。

当实际处理程序函数在SessionEvents.do_orm_execute()中返回Result对象,并传播到调用的Session.execute()方法时,Session.execute()方法的其余部分被抢占,Result对象立即返回给Session.execute()的调用者。

参数:

  • statement – 可选的要调用的语句,代替当前由ORMExecuteState.statement表示的语句。
  • params – 可选的参数字典或参数列表,将合并到此ORMExecuteState的现有ORMExecuteState.parameters中。 从版本 2.0 开始更改:接受参数字典列表进行 executemany 执行。
  • execution_options – 可选的执行选项字典将合并到此ORMExecuteState的现有ORMExecuteState.execution_options中。
  • bind_arguments – 可选的绑定参数字典,将在此ORMExecuteState的当前ORMExecuteState.bind_arguments中合并。

返回值:

一个带有 ORM 级别结果的Result对象。

另请参阅

重新执行语句 - 关于适当使用 ORMExecuteState.invoke_statement() 的背景和示例。

代码语言:javascript复制
attribute is_column_load

如果操作是刷新现有 ORM 对象上的面向列的属性,则返回 True。

在诸如 Session.refresh() 之类的操作期间发生,以及在加载由 defer() 推迟的属性时,或者正在加载已由 Session.expire() 直接或通过提交操作过期的属性时。

当发生此类操作时,处理程序很可能不希望向查询添加任何选项,因为查询应该是一个直接的主键获取,不应该有任何额外的 WHERE 条件,并且随实例传递的加载器选项已经添加到查询中。

新版本 1.4.0b2 中新增。

另请参阅

ORMExecuteState.is_relationship_load

代码语言:javascript复制
attribute is_delete

如果这是一个 DELETE 操作,则返回 True。

在版本 2.0.30 中更改:- 该属性对于自身针对 Delete 构造的 Select.from_statement() 构造也为 True,例如 select(Entity).from_statement(delete(..))

代码语言:javascript复制
attribute is_executemany

如果参数是一个多元素字典列表,并且有多个字典,则返回 True。

新版本 2.0 中新增。

代码语言:javascript复制
attribute is_from_statement

��果这是一个 Select.from_statement() 操作,则返回 True。

这与 ORMExecuteState.is_select 独立,因为 select().from_statement() 构造也可以与 INSERT/UPDATE/DELETE RETURNING 类型的语句一起使用。只有在 Select.from_statement() 本身针对 Select 构造时,才会设置 ORMExecuteState.is_select

新版本 2.0.30 中新增。

代码语言:javascript复制
attribute is_insert

如果这是一个 INSERT 操作,则返回 True。

在版本 2.0.30 中更改:- 对于Select.from_statement()构造本身针对Insert构造,例如select(Entity).from_statement(insert(..)),该属性也为 True

代码语言:javascript复制
attribute is_orm_statement

如果操作是 ORM 语句,则返回 True。

这表明调用 select()、insert()、update()或 delete()包含 ORM 实体作为主题。对于不包含 ORM 实体而仅引用Table元数据的语句,它被调用为核心 SQL 语句,并且不会发生 ORM 级别的自动化。

代码语言:javascript复制
attribute is_relationship_load

如果此加载正在代表关系加载对象,则返回 True。

这意味着,实际上加载程序是一个 LazyLoader、SelectInLoader、SubqueryLoader 或类似的加载程序,并且整个 SELECT 语句是代表一个关系加载发出的。

当发生此类操作时,处理程序很可能不希望向查询添加任何选项,因为加载程序选项已经能够传播到关系加载程序并且应该已经存在。

另请参阅

ORMExecuteState.is_column_load

代码语言:javascript复制
attribute is_select

如果这是一个选择操作,则返回 True。

在版本 2.0.30 中更改:- 对于Select.from_statement()构造本身针对Select构造,例如select(Entity).from_statement(select(..)),该属性也为 True

代码语言:javascript复制
attribute is_update

如果这是一个更新操作,则返回 True。

在版本 2.0.30 中更改:- 对于Select.from_statement()构造本身针对Update构造,例如select(Entity).from_statement(update(..)),该属性也为 True

代码语言:javascript复制
attribute lazy_loaded_from

使用此语句执行进行惰性加载操作的InstanceState

此属性的主要原因是支持水平分片扩展,该扩展在此扩展创建的特定查询执行时间挂钩中可用。为此,该属性仅打算在查询执行时间有意义,并且重要的是不包括任何之前的时间,包括查询编译时间。

代码语言:javascript复制
attribute load_options

返回将用于此执行的 load_options。

代码语言:javascript复制
attribute loader_strategy_path

返回当前加载路径的PathRegistry

此对象表示在查询中沿着关系的“路径”时,加载特定对象或集合的情况。

代码语言:javascript复制
attribute local_execution_options: _ExecuteOptions

传递给Session.execute()方法的执行选项的字典视图。

此处不包括与所调用语句相关的选项。

另请参阅

ORMExecuteState.execution_options

代码语言:javascript复制
attribute parameters: _CoreAnyExecuteParams | None

传递给Session.execute()的参数字典。

代码语言:javascript复制
attribute session: Session

正在使用的Session

代码语言:javascript复制
attribute statement: Executable

所调用的 SQL 语句。

对于从Query检索的 ORM 选择,这是从 ORM 查询生成的select的一个实例。

代码语言:javascript复制
attribute update_delete_options

返回将用于此执行的 update_delete_options。

代码语言:javascript复制
method update_execution_options(**opts: Any) → None

使用新值更新本地执行选项。

代码语言:javascript复制
attribute user_defined_options

已与所调用语句相关联的UserDefinedOptions序列。

代码语言:javascript复制
class sqlalchemy.orm.Session

管理 ORM 映射对象的持久性操作。

Session不适合在并发线程中使用。请参阅 Session 线程安全吗?AsyncSession 在并发任务中安全共享吗?了解背景信息。

关于 Session 的使用范例,请参阅使用 Session。

成员

init(), add(), add_all(), begin(), begin_nested(), bind_mapper(), bind_table(), bulk_insert_mappings(), bulk_save_objects(), bulk_update_mappings(), close(), close_all(), commit(), connection(), delete(), deleted, dirty, enable_relationship_loading(), execute(), expire(), expire_all(), expunge(), expunge_all(), flush(), get(), get_bind(), get_nested_transaction(), get_one(), get_transaction(), identity_key(), identity_map, in_nested_transaction(), in_transaction(), info, invalidate(), is_active, is_modified(), merge(), new, no_autoflush, object_session(), prepare(), query(), refresh(), reset(), rollback(), scalar(), scalars()

类签名

sqlalchemy.orm.Session (sqlalchemy.orm.session._SessionClassMethods, sqlalchemy.event.registry.EventTarget)

代码语言:javascript复制
method __init__(bind: _SessionBind | None = None, *, autoflush: bool = True, future: Literal[True] = True, expire_on_commit: bool = True, autobegin: bool = True, twophase: bool = False, binds: Dict[_SessionBindKey, _SessionBind] | None = None, enable_baked_queries: bool = True, info: _InfoType | None = None, query_cls: Type[Query[Any]] | None = None, autocommit: Literal[False] = False, join_transaction_mode: JoinTransactionMode = 'conditional_savepoint', close_resets_only: bool | _NoArg = _NoArg.NO_ARG)

构造一个新的Session

请参见sessionmaker函数,该函数用于生成带有给定参数集的Session产生的可调用对象。

参数:

autoflush

当为True时,所有查询操作将在继续之前对此Session执行Session.flush()调用。这是一个方便的特性,使得不需要反复调用Session.flush()以便数据库查询检索结果。

请参见

刷新 - 关于自动刷新的额外背景信息

autobegin

在请求操作时自动启动事务(即等同于调用Session.begin()) 。默认为True。设置为False以防止Session在构造之后以及在调用任何 Session.rollback()Session.commit()Session.close() 方法之后隐式开始事务。

从 2.0 版本开始新增。

请参见

禁用 Autobegin 以防止隐式事务

bind – 可选的EngineConnection,应该绑定到此Session。指定时,此会话执行的所有 SQL 操作将通过此可连接对象执行。

binds

一个字典,可能指定任意数量的EngineConnection对象作为 SQL 操作的连接源,以实体为单位。字典的键由任何一系列映射类、任意 Python 类(作为映射类的基类)、Table对象和Mapper对象组成。然后,字典的值是Engine的实例,或者较少见的是Connection对象。针对特定映射类进行的操作将查阅此字典,以确定哪个Engine应该用于特定的 SQL 操作。解析的完整启发式描述在Session.get_bind()中。用法示例如下:

代码语言:javascript复制
Session = sessionmaker(binds={
    SomeMappedClass: create_engine('postgresql psycopg2://engine1'),
    SomeDeclarativeBase: create_engine('postgresql psycopg2://engine2'),
    some_mapper: create_engine('postgresql psycopg2://engine3'),
    some_table: create_engine('postgresql psycopg2://engine4'),
    })

另请参见

分区策略(例如,每个会话多个数据库后端)

Session.bind_mapper()

Session.bind_table()

Session.get_bind()

class_ – 指定除了 sqlalchemy.orm.session.Session 外应该由返回的类使用的替代类。这是唯一作为 sessionmaker 函数本地的参数,并且不直接发送到 Session 的构造函数。

enable_baked_queries

遗留;默认为 True。由 sqlalchemy.ext.baked 扩展使用的参数,用于确定是否应缓存“烘焙查询”,如此扩展的正常操作所用。当设置为 False 时,此特定扩展使用的缓存被禁用。

从版本 1.4 起更改:sqlalchemy.ext.baked 扩展是遗留的,并且没有被 SQLAlchemy 的任何内部使用。因此,此标志仅影响明确在其自己的代码中使用此扩展的应用程序。

expire_on_commit

默认为 True。当为 True 时,每次 commit() 后所有实例都将完全过期,以便在完成事务后的所有属性/对象访问加载最新的数据库状态。

另请参见 提交

future

已弃用;此标志始终为 True。

另请参见

SQLAlchemy 2.0 - 主要迁移指南

info – 可选字典,与此 Session 关联的任意数据。可通过 Session.info 属性访问。请注意,字典在构造时被复制,因此对每个 Session 字典的修改将局限于该 Session

query_cls – 应该用于创建新的查询对象的类,由 Session.query() 方法返回。默认为 Query

twophase – 当设置为True时,所有事务都将作为“两阶段”事务启动,即使用正在使用的数据库的“两阶段”语义以及一个 XID。在commit()之后,对所有已附加数据库发出flush()后,将调用每个数据库的TwoPhaseTransaction.prepare()方法的TwoPhaseTransaction。这允许每个数据库在提交每个事务之前回滚整个事务。

autocommitautocommit关键字出现是为了向后兼容,但必须保持其默认值为False

join_transaction_mode

描述了在给定绑定是Session之外已经开始事务的Connection时应采取的事务行为;换句话说,Connection.in_transaction()方法返回 True。

以下行为仅在Session 实际使用给定的连接时才生效;也就是说,诸如Session.execute()Session.connection()等方法实际上被调用:

  • "conditional_savepoint" - 这是默认行为。如果给定的Connection在事务中开始但没有 SAVEPOINT,则使用"rollback_only"。如果Connection此外还在 SAVEPOINT 中,换句话说,Connection.in_nested_transaction()方法返回 True,则使用"create_savepoint""conditional_savepoint" 行为试图利用保存点来保持现有事务的状态不变,但仅在已经存在保存点的情况下;否则,不假设所使用的后端具有足够的 SAVEPOINT 支持,因为该功能的可用性有所不同。 "conditional_savepoint" 还试图与先前 Session 行为建立大致的向后兼容性,用于未设置特定模式的应用程序。建议使用其中一个明确的设置。
  • "create_savepoint" - Session 将在所有情况下使用 Connection.begin_nested() 来创建自己的事务。这个事务本质上是“在顶部”的任何存在的事务之上打开的;如果底层数据库和正在使用的驱动程序完全支持 SAVEPOINT,那么外部事务将在 Session 生命周期内保持不受影响。 "create_savepoint" 模式对于将 Session 集成到测试套件中并保持外部启动的事务不受影响最为有用;然而,它依赖于底层驱动程序和数据库的正确 SAVEPOINT 支持。 提示 使用 SQLite 时,Python 3.11 中包含的 SQLite 驱动在某些情况下不能正确处理 SAVEPOINTs,需要通过一些变通方法。请参阅 Serializable isolation / Savepoints / Transactional DDL 和 Serializable isolation / Savepoints / Transactional DDL(asyncio 版本)部分,了解当前的解决方法详情。
  • "control_fully" - Session 将接管给定的事务作为自己的事务;Session.commit() 将在事务上调用 .commit()Session.rollback() 将在事务上调用 .rollback()Session.close() 将调用事务的 .rollback。 提示 此使用模式相当于 SQLAlchemy 1.4 如何处理具有现有 SAVEPOINT 的Connection(即Connection.begin_nested()); Session将完全控制现有 SAVEPOINT。
  • "rollback_only" - Session将仅控制给定事务进行.rollback()调用;.commit()调用不会传播到给定事务。.close()调用对给定事务没有影响。 提示 此使用模式相当于 SQLAlchemy 1.4 如何处理具有现有常规数据库事务的Connection(即Connection.begin()); Session将传播Session.rollback()调用到底层事务,但不会传播Session.commit()Session.close()调用。

在版本 2.0.0rc1 中新增。

close_resets_only

默认为True。确定在调用.close()后会话是否应重置自身,或者应传入不再可用的状态,禁用重用。

新版本 2.0.22 中新增标志close_resets_only。将来的 SQLAlchemy 版本可能会将此标志的默认值更改为False

另请参阅

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

代码语言:javascript复制
method add(instance: object, _warn: bool = True) → None

将对象放入此Session

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

当传递给Session.add()方法时处于分离状态的对象将直接转移到持久化状态。

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

另请参见

Session.add_all()

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

代码语言:javascript复制
method add_all(instances: Iterable[object]) → None

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

请参阅Session.add()的文档以获取一般行为描述。

另请参见

Session.add()

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

代码语言:javascript复制
method begin(nested: bool = False) → SessionTransaction

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

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

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

参数:

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

返回:

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

另请参见

自动开始

管理事务

Session.begin_nested()

代码语言:javascript复制
method begin_nested() → SessionTransaction

在此会话上开始“嵌套”事务,例如 SAVEPOINT。

目标数据库和相关驱动程序必须支持 SQL SAVEPOINT 才能使此方法正常运行。

有关 SAVEPOINT 事务的文档,请参阅使用 SAVEPOINT。

返回:

SessionTransaction对象。请注意,SessionTransaction作为上下文管理器,允许在“with”块中使用Session.begin_nested()。请参阅使用 SAVEPOINT 获取用法示例。

另请参阅

使用 SAVEPOINT

可序列化隔离/保存点/事务性 DDL - 针对 SQLite 驱动程序需要特殊的解决方案,以使 SAVEPOINT 正常工作。对于 asyncio 用例,请参阅可序列化隔离/保存点/事务性 DDL(asyncio 版本)部分。

代码语言:javascript复制
method bind_mapper(mapper: _EntityBindKey[_O], bind: _SessionBind) → None

Mapper或任意 Python 类与“bind”相关联,例如EngineConnection

给定的实体被添加到Session.get_bind()方法使用的查找中。

参数:

  • mapper – 一个Mapper对象,或者是一个映射类的实例,或者是任何作为一组映射类基类的 Python 类。
  • bind – 一个EngineConnection对象。

另请参阅

分区策略(例如每个会话多个数据库后端)

Session.binds

Session.bind_table()

代码语言:javascript复制
method bind_table(table: TableClause, bind: Engine | Connection) → None

Table与“bind”相关联,例如EngineConnection

给定的Table被添加到Session.get_bind()方法使用的查找中。

参数:

  • table – 一个Table对象,通常是 ORM 映射的目标,或者存在于被映射的可选择性内。
  • bind – 一个EngineConnection对象。

另请参阅

分区策略(例如每个 Session 多个数据库后端)

Session.binds

Session.bind_mapper()

代码语言:javascript复制
method bulk_insert_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]], return_defaults: bool = False, render_nulls: bool = False) → None

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

旧特性

该方法是 SQLAlchemy 2.0 系列的旧特性。对于现代的批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句和 ORM 按主键批量 UPDATE 部分。2.0 API 与此方法共享实现细节,并添加了新功能。

参数:

  • mapper – 一个映射类,或者实际的Mapper对象,表示映射列表中表示的单一对象类型。
  • mappings – 一个字典序列,每个字典包含要插入的映射行的状态,以映射类上的属性名称为准。如果映射涉及多个表,比如联合继承映射,每个字典必须包含要填充到所有表中的所有键。
  • return_defaults – 当为 True 时,INSERT 过程将被修改以确保新生成的主键值将被获取。通常此参数的理由是为了使联合表继承映射能够进行批量插入。 注意 对于不支持 RETURNING 的后端,Session.bulk_insert_mappings.return_defaults参数可以显著降低性能,因为 INSERT 语句不能再批量处理。请参阅“插入多个值”行为对 INSERT 语句的影响以了解哪些后端受到影响。
  • render_nulls – 当为 True 时,None值将导致在 INSERT 语句中包含一个 NULL 值,而不是将列从 INSERT 中省略。这允许所有被 INSERT 的行具有相同的列集,从而允许将完整的行集批量发送到 DBAPI。通常,每个包含与前一行不同的 NULL 值组合的列集必须从渲染的 INSERT 语句中省略不同的列系列,这意味着必须将其作为单独的语句发出。通过传递此标志,可以确保将完整的行集批量处理为一个批次;但成本是,通过省略的列调用的服务器端默认值将被跳过,因此必须确保这些不是必需的。 警告 当设置了此标志时,服务器端默认的 SQL 值不会被调用,对于那些以 NULL 插入的列;NULL 值将被显式发送。必须确保整个操作不需要调用任何服务器端默认函数。

另请参阅

启用 ORM 的 INSERT、UPDATE 和 DELETE 语句

Session.bulk_save_objects()

Session.bulk_update_mappings()

代码语言:javascript复制
method bulk_save_objects(objects: Iterable[object], return_defaults: bool = False, update_changed_only: bool = True, preserve_order: bool = True) → None

对给定对象列表执行批量保存。

旧特性

该方法是 SQLAlchemy 2.0 系列的一个旧特性。对于现代的批量 INSERT 和 UPDATE,请参阅 ORM 批量 INSERT 语句和按主键批量 UPDATE 部分。

对于一般的 INSERT 和更新现有 ORM 映射对象,建议使用标准的工作单元数据管理模式,介绍在 SQLAlchemy 统一教程中的 ORM 数据操作。SQLAlchemy 2.0 现在使用现代方言的“插入多个值”行为用于 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 启用的 INSERT、UPDATE 和 DELETE 语句

Session.bulk_insert_mappings()

Session.bulk_update_mappings()

代码语言:javascript复制
method bulk_update_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]]) → None

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

遗留特性

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

参数:

  • mapper – 映射类,或者表示映射列表中所表示的单个对象的实际Mapper对象。
  • mappings - 一个字典序列,每个字典包含要更新的映射行的状态,以映射类上的属性名称表示。如果映射涉及多个表,例如连接继承映射,每个字典可能包含与所有表对应的键。所有那些存在且不是主键的键将应用于 UPDATE 语句的 SET 子句;必需的主键值将应用于 WHERE 子句。

另请参阅

启用 ORM 的 INSERT、UPDATE 和 DELETE 语句

Session.bulk_insert_mappings()

Session.bulk_save_objects()

代码语言:javascript复制
method close() → None

关闭此Session使用的事务资源和 ORM 对象。

这将清除与此Session关联的所有 ORM 对象,结束任何正在进行的事务,并释放此Session自身从关联的Engine对象中签出的任何Connection对象。然后,该操作将使Session处于可以再次使用的状态。

提示

在默认运行模式下,Session.close()方法不会阻止再次使用 SessionSession本身实际上没有明确的“关闭”状态;它仅意味着Session将释放所有数据库连接和 ORM 对象。

将参数Session.close_resets_only设置为False将使close变为最终状态,这意味着对会话的任何进一步操作都将被禁止。

从版本 1.4 开始更改:Session.close()方法不会立即创建新的SessionTransaction对象;相反,只有在再次为数据库操作使用Session时才会创建新的SessionTransaction

另请参阅

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

Session.reset() - 与参数Session.close_resets_only设置为Trueclose()类似的方法。

代码语言:javascript复制
classmethod close_all() → None

sqlalchemy.orm.session._SessionClassMethods.close_all 方法继承

关闭内存中的所有会话。

从版本 1.3 开始已废弃:Session.close_all() 方法已被废弃,并将在将来的版本中删除。请参考 close_all_sessions()

代码语言:javascript复制
method commit() → None

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

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

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

最外层的数据库事务会无条件提交,自动释放任何当前有效的 SAVEPOINT。

另请参阅

提交

事务管理

在使用 AsyncSession 时避免隐式 IO

代码语言:javascript复制
method connection(bind_arguments: _BindArguments | None = None, execution_options: CoreExecuteOptionsParameter | None = None) → Connection

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

返回与当前事务对应的Connection,或者如果没有进行中的事务,则开始一个新事务并返回Connection(请注意,在发出第一条 SQL 语句之前,不会与 DBAPI 建立事务状态)。

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

参数:

  • bind_arguments – 绑定参数字典。可能包括“mapper”、“bind”、“clause”等传递给Session.get_bind()的其他自定义参数。
  • execution_options – 一个执行选项字典,将仅在首次获取连接时传递给Connection.execution_options()。如果连接已经存在于Session中,则会发出警告并忽略参数。 另请参见 设置事务隔离级别 / DBAPI AUTOCOMMIT
代码语言:javascript复制
method delete(instance: object) → None

将实例标记为已删除。

假定传递的对象在调用方法后将保持在 persistent 或 detached 状态;在下次刷新之前,对象将保持在 persistent 状态。在此期间,对象还将是Session.deleted集合的成员。

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

另请参见

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

代码语言:javascript复制
attribute deleted

在此Session中标记为‘deleted’的所有实例的集合

代码语言:javascript复制
attribute dirty

所有被视为脏数据的持久实例的集合。

例如:

代码语言:javascript复制
some_mapped_object in session.dirty

当实例被修改但未被删除时,被视为脏数据。

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

要检查实例的属性是否具有可执行的净变化,请使用Session.is_modified()方法。

代码语言:javascript复制
method enable_relationship_loading(obj: object) → None

将对象与此Session关联以加载相关对象。

警告

enable_relationship_loading()存在于服务于特殊用例,并不建议一般使用。

通过relationship()映射的属性访问将尝试使用此Session作为连接的源来从数据库加载值。这些值将根据此对象上存在的外键和主键值进行加载 - 如果不存在,则这些关系将不可用。

对象将附加到此会话,但将不会参与任何持久化操作;对于几乎所有目的,其状态仍将保持“瞬态”或“分离”,除了关系加载的情况。

还请注意,反向引用通常不会按预期工作。在目标对象上修改与关系绑定的属性可能不会触发反向引用事件,如果有效值已从保存外键值中加载,则是如此。

Session.enable_relationship_loading()方法类似于relationship()上的load_on_pending标志。与该标志不同,Session.enable_relationship_loading()允许对象保持瞬态状态,同时仍然能够加载相关项目。

要使一个临时对象与Session相关联,可以通过Session.enable_relationship_loading()将其添加到Session中。如果该对象代表数据库中现有的标识,则应使用Session.merge()进行合并。

Session.enable_relationship_loading()在正常使用 ORM 时不会改善行为 - 对象引用应该在对象级别构建,而不是在外键级别构建,以便它们在 flush()继续之前以普通方式存在。此方法不适用于一般用途。

另请参见

relationship.load_on_pending - 此标志允许在待处理项目上对多对一关系进行逐个加载。

make_transient_to_detached() - 允许将对象添加到Session中而不发出 SQL,然后在访问时取消过期属性。

代码语言:javascript复制
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 表达式构造。

返回代表语句执行结果的Result对象。

例如:

代码语言:javascript复制
from sqlalchemy import select
result = session.execute(
    select(User).where(User.id == 5)
)

Session.execute()的 API 契约类似于Connection.execute()的契约,是Connection的 2.0 风格版本。

从版本 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对象。

代码语言:javascript复制
method expire(instance: object, attribute_names: Iterable[str] | None = None) → None

使实例上的属性过期。

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

要同时使Session中的所有对象过期,请使用Session.expire_all()

Session对象的默认行为是在调用Session.rollback()Session.commit()方法时使所有状态过期,以便为新事务加载新状态。因此,仅在当前事务中发出非 ORM SQL 语句的情况下调用Session.expire()才有意义。

参数:

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

另请参见

刷新/过期 - 介绍性材料

Session.expire()

Session.refresh()

Query.populate_existing()

代码语言:javascript复制
method expire_all() → None

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

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

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

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

另请参阅

刷新/过期 - 简介材料

Session.expire()

Session.refresh()

Query.populate_existing()

代码语言:javascript复制
method expunge(instance: object) → None

从此Session中删除实例。

这将释放所有对实例的内部引用。级联将根据expunge级联规则应用。

代码语言:javascript复制
method expunge_all() → None

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

这相当于在此Session中调用expunge(obj)以将所有对象从中清除。

代码语言:javascript复制
method flush(objects: Sequence[Any] | None = None) → None

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

将所有待处理的对象创建、删除和修改操作写入数据库,作为 INSERTs、DELETEs、UPDATEs 等。操作会自动按照会话的工作单元依赖解析器的顺序进行排序。

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

参数:

objects

可选;仅将刷新操作限制为仅操作给定集合中的元素。

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

代码语言:javascript复制
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

示例:

代码语言:javascript复制
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”,则调用如下:

代码语言:javascript复制
my_object = session.get(SomeClass, 5)

元组形式通常按照它们与映射的Table对象的主键列对应的顺序排列,或者如果使用了Mapper.primary_key配置参数,则按照该参数的使用顺序排列。例如,如果一行的主键由整数数字“5, 10”表示,则调用将如下所示:

代码语言:javascript复制
my_object = session.get(SomeClass, (5, 10))

字典形式应该将每个主键元素对应的映射属性名称作为键。如果映射类具有存储对象主键值的属性idversion_id,则调用将如下所示:

代码语言:javascript复制
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

代码语言:javascript复制
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所绑定到的“绑定”。

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

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

请注意,当通过 ORM 操作(例如Session.query()Session.flush()调用等)调用Session.get_bind()时,“mapper”参数通常存在。

解析的顺序是:

  1. 如果提供了 mapper 并且Session.binds存在,则根据使用的 mapper,然后根据使用的 mapped 类,然后根据 mapped 类的__mro__中存在的任何基类,从更具体的超类到更一般的超类来定位一个绑定。
  2. 如果给定了子句并且存在Session.binds,则基于Session.binds中存在的给定子句中找到的Table对象定位一个绑定。
  3. 如果存在Session.binds,则返回该绑定。
  4. 如果给定了子句,则尝试返回与最终与子句关联的MetaData相关联的绑定。
  5. 如果给定了映射器,则尝试返回与最终与映射器映射到的Table或其他可选择的绑定相关联的MetaData
  6. 找不到绑定时,将引发UnboundExecutionError

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

参数:

  • mapper – 可选的映射类或对应的Mapper实例。绑定可以首先从与此Session关联的“binds”映射中派生Mapper,其次通过查看与Mapper映射到的Table相关联的MetaData来获取。
  • clause – 一个ClauseElement(即select()text()等)。如果mapper参数不存在或无法生成绑定,则将搜索给定表达式构造的绑定元素,通常是与绑定的MetaData相关联的Table

另请参阅

分区策略(例如每个 Session 多个数据库后���)

Session.binds

Session.bind_mapper()

Session.bind_table()

代码语言:javascript复制
method get_nested_transaction() → SessionTransaction | None

返回当前正在进行的嵌套事务,如果有的话。

版本 1.4 中的新功能。

代码语言:javascript复制
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

根据给定的主键标识符返回一个实例,如果未找到则引发异常。

如果查询未选择任何行,则引发sqlalchemy.orm.exc.NoResultFound

有关参数的详细文档,请参见方法Session.get()

版本 2.0.22 中的新功能。

返回:

对象实例。

另请参见

Session.get() - 相当的方法,而不是

如果未找到具有提供的主键的行,则返回None

代码语言:javascript复制
method get_transaction() → SessionTransaction | None

返回当前正在进行的根事务,如果有的话。

版本 1.4 中的新功能。

代码语言:javascript复制
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]

继承自 sqlalchemy.orm.session._SessionClassMethods.identity_key 方法的 sqlalchemy.orm.session._SessionClassMethods

返回一个标识键。

这是identity_key()的别名。

代码语言:javascript复制
attribute identity_map: IdentityMap

对象标识与对象本身的映射。

通过遍历Session.identity_map.values()可以访问当前会话中的所有持久对象的完整集合(即具有行标识的对象)。

另请参见

identity_key() - 用于生成此字典中使用的键的辅助函数。

代码语言:javascript复制
method in_nested_transaction() → bool

如果此Session已开始嵌套事务(例如 SAVEPOINT),则返回 True。

版本 1.4 中的新功能。

代码语言:javascript复制
method in_transaction() → bool

如果此Session已开始事务,则返回 True。

版本 1.4 中的新功能。

另请参见

Session.is_active

代码语言:javascript复制
attribute info

用户可修改的字典。

此字典的初始值可以使用Session构造函数或sessionmaker构造函数或工厂方法的info参数进行填充。此处的字典始终局限于此Session,可以独立于所有其他Session对象进行修改。

代码语言:javascript复制
method invalidate() → None

使用连接失效关闭此会话。

这是Session.close()的变体,还将确保在当前用于事务的每个Connection对象上调用Connection.invalidate()方法(通常只有一个连接,除非Session与多个引擎一起使用)。

当已知数据库处于不再安全使用连接的状态时,可以调用此方法。

下面说明了使用gevent时可能出现的Timeout异常的情况,这可能意味着应丢弃底层连接:

代码语言:javascript复制
import gevent

try:
    sess = Session()
    sess.add(User())
    sess.commit()
except gevent.Timeout:
    sess.invalidate()
    raise
except:
    sess.rollback()
    raise

该方法还执行Session.close()执行的所有操作,包括清除所有 ORM 对象。

代码语言:javascript复制
attribute is_active

如果此Session不处于“部分回滚”状态,则为 True。

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

“部分回滚”状态通常表示Session的刷新过程失败,并且必须发出Session.rollback()方法以完全回滚事务。

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

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

另请参见

“由于在刷新期间发生的先前异常,此会话的事务已回滚。”(或类似内容)

Session.in_transaction()

代码语言:javascript复制
method is_modified(instance: object, include_collections: bool = True) → bool

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

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

实际上,这是一种更昂贵和准确的版本,用于检查给定实例是否存在于 Session.dirty 集合中;对每个属性的净“脏”状态进行了完整测试。

例如:

代码语言:javascript复制
return session.is_modified(someobject)

这种方法有一些注意事项:

  • 当测试使用此方法时,存在于 Session.dirty 集合中的实例可能会报告 False。这是因为对象可能已通过属性变化接收到更改事件,从而将其放置在 Session.dirty 中,但最终状态与从数据库加载的状态相同,在这里没有净变化。
  • 当新值被应用时,标量属性可能没有记录先前设置的值,如果属性在接收到新值时没有被加载或已过期,则假定属性发生了变化,即使最终与其数据库值相比没有净变化,在大多数情况下,当设置事件发生时,SQLAlchemy 不需要“旧”值,因此,如果旧值不存在,则跳过发出 SQL 调用的开销,这是基于这样一个假设:通常需要更新标量值,并且在那些极少数情况下,其中不需要,平均而言,这比发出防御性 SELECT 更便宜。 只有当属性容器的 active_history 标志设置为 True 时,才无条件地在设置时获取“旧”值。此标志通常设置为主键属性和非简单一对多的标量对象引用。要为任意映射列设置此标志,请使用 column_property() 中的 active_history 参数。

参数:

  • instance – 要测试是否存在待处理更改的映射实例。
  • include_collections – 指示是否应该在操作中包含多值集合。将其设置为 False 是一种检测仅基于本地列的属性(即标量列或一对多外键),这将导致此实例在刷新时进行更新。
代码语言:javascript复制
method merge(instance: _O, *, load: bool = True, options: Sequence[ORMOption] | None = None) → _O

将给定实例的状态复制到此 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 的另一种方法。

代码语言:javascript复制
attribute new

在此Session中标记为“新”的所有实例的集合。

代码语言:javascript复制
attribute no_autoflush

返回一个禁用自动冲刷的上下文管理器。

例如:

代码语言:javascript复制
with session.no_autoflush:

    some_object = SomeClass()
    session.add(some_object)
    # won't autoflush
    some_object.related_thing = session.query(SomeRelated).first()

with: 块内进行的操作不会受到查询访问时发生的 flush 的影响。这在初始化一系列涉及现有数据库查询的对象时很有用,此时尚未完成的对象不应立即被 flush。

代码语言:javascript复制
classmethod object_session(instance: object) → Session | None

继承自 sqlalchemy.orm.session._SessionClassMethods sqlalchemy.orm.session._SessionClassMethods.object_session 方法

返回一个对象所属的Session

这是 object_session() 方法的别名。

代码语言:javascript复制
method prepare() → None

准备进行中的当前事务以进行两阶段提交。

如果没有进行中的事务,则此方法会引发一个InvalidRequestError

仅两阶段会话的根事务才能被准备。如果当前事务不是这样的事务,则会引发 InvalidRequestError

代码语言:javascript复制
method query(*entities: _ColumnsClauseArgument[Any], **kwargs: Any) → Query[Any]

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

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

另请参阅

SQLAlchemy 统一教程

ORM 查询指南

旧版查询 API - 旧版 API 文档

代码语言:javascript复制
method refresh(instance: object, attribute_names: Iterable[str] | None = None, with_for_update: ForUpdateParameter = None) → None

过期并刷新给定实例上的属性。

选定的属性将首先被过期,就像使用 Session.expire() 时一样;然后会向数据库发出 SELECT 语句,以当前事务中可用的当前值刷新基于列的属性。

如果对象已经急加载,那么以relationship()为导向的属性也将立即加载,使用最初加载时的相同的急加载策略。

1.4 版本新增:- Session.refresh() 方法还可以立即刷新急加载的属性。

relationship()定向属性通常使用select(或“lazy”)加载器策略将在属性名称集合中明确命名时也会加载**,使用immediate加载器策略发出用于属性的 SELECT 语句。如果惰性加载的关系未在Session.refresh.attribute_names中命名,则它们将保持为“惰性加载”属性,并且不会被隐式刷新。

从版本 2.0.4 开始更改:Session.refresh()方法现在将刷新在Session.refresh.attribute_names集合中明确命名的惰性加载的relationship()定向属性。

提示

虽然Session.refresh()方法能够刷新列和关系定向属性,但其主要重点是刷新单个实例上的本地列定向属性。对于更开放的“刷新”功能,包括能够同时刷新多个对象的属性并明确控制关系加载器策略,请改用填充现有功能。

请注意,高度隔离的事务将返回与先前在该事务中读取的相同值,而不考虑该事务之外数据库状态的更改。通常只在事务开始时数据库行尚未被访问时刷新属性才有意义。

参数:

  • attribute_names – 可选。一个包含字符串属性名称的可迭代集合,指示要刷新的属性子集。
  • with_for_update – 可选布尔值True表示应使用 FOR UPDATE,或者可以是一个包含标志的字典,指示用于 SELECT 的更具体的 FOR UPDATE 标志集;标志应与Query.with_for_update()参数匹配。取代Session.refresh.lockmode参数。

另请参阅

刷新/过期 - 入门材料

Session.expire()

Session.expire_all()

填充现有对象 - 允许任何 ORM 查询刷新对象,就像它们通常加载的那样。

代码语言:javascript复制
method reset() → None

关闭事务资源和此Session使用的 ORM 对象,将会重置会话到其初始状态。

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

新版本 2.0.22 中新增。

另请参阅

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

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

代码语言:javascript复制
method rollback() → None

回滚当前进行中的事务。

如果没有进行中的事务,则此方法是一个传递方法。

该方法始终回滚最顶层的数据库事务,丢弃可能正在进行的任何嵌套事务。

另请参阅

回滚操作

事务管理

代码语言:javascript复制
method scalar(statement: Executable, params: _CoreSingleExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) → Any

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

使用和参数与Session.execute()相同;返回结果是一个标量 Python 值。

代码语言:javascript复制
method scalars(statement: Executable, params: _CoreAnyExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) → ScalarResult[Any]

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

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

返回:

一个ScalarResult对象

新版本 1.4.24 中新增:添加Session.scalars()

新版本 1.4.26 中新增:添加scoped_session.scalars()

另请参阅

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

代码语言:javascript复制
class sqlalchemy.orm.SessionTransaction

一个 Session 级别的事务。

SessionTransaction 是从 Session.begin()Session.begin_nested() 方法中生成的。它在现代用法中主要是一个为会话事务提供上下文管理器的内部对象。

SessionTransaction 交互的文档位于:管理事务。

在版本 1.4 中更改:与 SessionTransaction 对象直接交互的作用域和 API 方法已经简化。

另请参阅

管理事务

Session.begin()

Session.begin_nested()

Session.rollback()

Session.commit()

Session.in_transaction()

Session.in_nested_transaction()

Session.get_transaction()

Session.get_nested_transaction()

成员

嵌套, origin, 父级

类签名

sqlalchemy.orm.SessionTransaction (sqlalchemy.orm.state_changes._StateChange, sqlalchemy.engine.util.TransactionalContext)

代码语言:javascript复制
attribute nested: bool = False

指示此事务是否为嵌套或 SAVEPOINT 事务。

SessionTransaction.nested 为 True 时,预期 SessionTransaction.parent 也将出现,并链接到封闭的 SessionTransaction

另请参见

SessionTransaction.origin

代码语言:javascript复制
attribute origin: SessionTransactionOrigin

SessionTransaction 的来源。

指的是一个 SessionTransactionOrigin 实例,它是一个枚举,指示导致构建此 SessionTransaction 的源事件。

新版本 2.0 中新增。

代码语言:javascript复制
attribute parent

SessionTransaction 的父 SessionTransaction

如果此属性为 None,表示此 SessionTransaction 处于堆栈顶部,并对应于真实的“COMMIT”/“ROLLBACK”块。 如果非 None,则这是一个“子事务”(刷新过程中使用的内部标记对象)或“嵌套”/保存点事��。 如果 SessionTransaction.nested 属性为 True,则这是一个保存点,如果为 False,则表示这是一个子事务。

代码语言:javascript复制
class sqlalchemy.orm.SessionTransactionOrigin

指示 SessionTransaction 的来源。

此枚举存在于任何 SessionTransaction 对象的 SessionTransaction.origin 属性上。

新版本 2.0 中新增。

成员

AUTOBEGIN, BEGIN, BEGIN_NESTED, SUBTRANSACTION

类签名

sqlalchemy.orm.SessionTransactionOrigin (enum.Enum)

代码语言:javascript复制
attribute AUTOBEGIN = 0

事务是由 autobegin 启动的。

代码语言:javascript复制
attribute BEGIN = 1

事务是通过调用 Session.begin() 开始的。

代码语言:javascript复制
attribute BEGIN_NESTED = 2

事务是通过 Session.begin_nested() 开始的。

代码语言:javascript复制
attribute SUBTRANSACTION = 3

事务是一个内部的“子事务”。

会话工具

对象名称

描述

close_all_sessions()

关闭内存中的所有会话。

make_transient(instance)

更改给定实例的状态,使其成为瞬态。

make_transient_to_detached(instance)

使给定的瞬态实例分离。

object_session(instance)

返回给定实例所属的Session。

was_deleted(object_)

如果给定对象在会话刷新中被删除,则返回 True。

代码语言:javascript复制
function sqlalchemy.orm.close_all_sessions() → None

关闭内存中的所有会话。

此函数查询所有Session对象的全局注册表,并调用Session.close()关闭它们,将它们重置为干净状态。

此函数不适用于一般用途,但可能对拆卸方案中的测试套件有用。

版本 1.3 中的新功能。

代码语言:javascript复制
function sqlalchemy.orm.make_transient(instance: object) → None

更改给定实例的状态,使其为瞬态。

注意

make_transient()是仅适用于高级用例的特殊函数。

假定给定的映射实例处于持久或分离状态。该函数将删除其与任何Session的关联以及其InstanceState.identity。其效果是对象将表现得像是新构造的,但保留在调用时加载的任何属性/集合值。如果此对象曾因使用Session.delete()而被删除,则InstanceState.deleted标志也将被重置。

警告

make_transient() “取消过期”或以其他方式急切加载在调用函数时尚未加载的 ORM 映射属性。这包括:

  • 通过Session.expire()过期
  • 作为提交会话事务的自然效果而过期,例如Session.commit()
  • 通常是延迟加载,但目前尚未加载
  • 被“延迟加载”(参见限制加载的列与列延迟)且尚未加载
  • 在加载此对象的查询中不存在,例如在联接表继承和其他场景中常见的情况。

调用 make_transient() 后,像上面这样未加载的属性通常在访问时将解析为值 None,或者对于集合定向属性为一个空集合。由于对象是瞬态的,并且未关联任何数据库标识,因此它将不再检索这些值。

另请参阅

make_transient_to_detached()

代码语言:javascript复制
function sqlalchemy.orm.make_transient_to_detached(instance: object) → None

使给定的瞬态实例 分离。

注意

make_transient_to_detached() 是一个仅限于高级用例的特殊情况函数。

在给定实例上的所有属性历史都将被重置,就像实例是从查询中新加载的一样。丢失的属性将被标记为过期。对象的主键属性将被制作为实例的“键”,这些主键属性是必需的。

然后对象可以被添加到一个会话中,或者可能与 load=False 标志合并,此时它将看起来像是以这种方式加载,而不发出 SQL。

这是一个特殊的用例函数,与对 Session.merge() 的正常调用不同,因为可以制造给定的持久状态而不进行任何 SQL 调用。

另请参阅

make_transient()

Session.enable_relationship_loading()

代码语言:javascript复制
function sqlalchemy.orm.object_session(instance: object) → Session | None

返回给定实例所属的 Session

这与 InstanceState.session 访问器本质上是相同的。有关详细信息,请参阅该属性。

代码语言:javascript复制
function sqlalchemy.orm.util.was_deleted(object_: object) → bool

返回 True,如果给定的对象在会话刷新内被删除。

不管对象是持久的还是分离的,都是如此。

另请参阅

InstanceState.was_deleted

属性和状态管理实用程序

这些函数由 SQLAlchemy 属性调制 API 提供,以提供一个详细的接口来处理实例、属性值和历史。当构造事件监听函数时,其中一些函数是有用的,比如 ORM 事件 中描述的那些函数。

对象名称

描述

del_attribute(instance, key)

删除属性的值,触发历史事件。

flag_dirty(instance)

标记一个实例为“脏”状态,而不需要特定的属性名称。

flag_modified(instance, key)

将实例上的属性标记为“已修改”。

get_attribute(instance, key)

获取属性的值,触发任何所需的可调用函数。

get_history(obj, key[, passive])

返回给定对象和属性键的History记录。

History

已添加、未更改和已删除值的 3 元组,表示在受监控属性上发生的更改。

init_collection(obj, key)

初始化一个集合属性并返回集合适配器。

instance_state

返回给定映射对象的InstanceState。

is_instrumented(instance, key)

如果给定实例上的给定属性由 attributes 包进行了插装,则返回 True。

object_state(instance)

给定一个对象,返回与该对象关联的InstanceState。

set_attribute(instance, key, value[, initiator])

设置属性的值,触发历史事件。

set_committed_value(instance, key, value)

设置属性的值,不触发历史事件。

代码语言:javascript复制
function sqlalchemy.orm.util.object_state(instance: _T) → InstanceState[_T]

给定一个对象,返回与该对象关联的InstanceState

如果未配置映射,则引发sqlalchemy.orm.exc.UnmappedInstanceError

相同的功能可以通过inspect()函数获得,如下所示:

代码语言:javascript复制
inspect(instance)

使用检查系统将在实例不属于映射的情况下引发sqlalchemy.exc.NoInspectionAvailable

代码语言:javascript复制
function sqlalchemy.orm.attributes.del_attribute(instance: object, key: str) → None

删除属性的值,触发历史事件。

无论直接应用于类的插装如何,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来建立由 SQLAlchemy 理解的属性状态。

代码语言:javascript复制
function sqlalchemy.orm.attributes.get_attribute(instance: object, key: str) → Any

获取属性的值,触发任何所需的可调用函数。

无论直接应用于类的仪器,都可以使用此功能,即不需要描述符。自定义属性管理方案将需要使用此方法来使用 SQLAlchemy 所理解的属性状态。

代码语言:javascript复制
function sqlalchemy.orm.attributes.get_history(obj: object, key: str, passive: PassiveFlag = symbol('PASSIVE_OFF')) → History

返回给定对象和属性键的History记录。

这是给定属性的预刷新历史记录,每次Session刷新更改到当前数据库事务时都会重置它。

注意

首选使用AttributeState.historyAttributeState.load_history()访问器来检索实例属性的History

参数:

  • obj – 一个其类由属性包仪器化的对象。
  • key – 字符串属性名称。
  • passive – 如果值尚不存在,则指示属性的加载行为。这是一个位标志属性,默认为PASSIVE_OFF,表示应发出所有必要的 SQL。

另请参见

AttributeState.history

AttributeState.load_history() - 如果值在本地不存在,则使用加载器可调用检索历史。

代码语言:javascript复制
function sqlalchemy.orm.attributes.init_collection(obj: object, key: str) → CollectionAdapter

初始化一个集合属性并返回集合适配器。

此函数用于为先前未加载的属性提供直接访问集合内部。例如:

代码语言:javascript复制
collection_adapter = init_collection(someobject, 'elements')
for elem in values:
    collection_adapter.append_without_event(elem)

对于执行上述操作的更简单方法,请参见set_committed_value()

参数:

  • obj – 一个映射对象
  • key – 集合所在的字符串属性名称。
代码语言:javascript复制
function sqlalchemy.orm.attributes.flag_modified(instance: object, key: str) → None

将实例上的属性标记为“已修改”。

这会在实例上设置“已修改”标志,并为给定属性建立一个无条件的更改事件。属性必须具有值,否则会引发InvalidRequestError

要标记一个对象为“脏”,而不引用任何特定属性,以便在刷新时考虑到它,使用flag_dirty()调用。

另请参见

flag_dirty()

代码语言:javascript复制
function sqlalchemy.orm.attributes.flag_dirty(instance: object) → None

将实例标记为“脏”,而不提及任何特定属性。

这是一个特殊操作,允许对象通过刷新流程进行拦截,例如 SessionEvents.before_flush()。请注意,对于没有更改的对象,在刷新过程中不会发出任何 SQL,即使通过此方法标记为脏。但是,SessionEvents.before_flush() 处理程序将能够在 Session.dirty 集合中看到对象,并可能对其进行更改,然后这些更改将包含在发出的 SQL 中。

自 1.2 版新功能。

另请参阅

flag_modified()

代码语言:javascript复制
function sqlalchemy.orm.attributes.instance_state()

返回给定映射对象的 InstanceState

此函数是 object_state() 的内部版本。此处推荐使用 object_state() 和/或 inspect() 函数,因为它们会在给定对象未映射时各自发出信息丰富的异常。

代码语言:javascript复制
function sqlalchemy.orm.instrumentation.is_instrumented(instance, key)

如果给定实例上的给定属性由 attributes 包进行仪器化,则返回 True。

无论直接应用于类的仪器如何,都可以使用此函数,即不需要描述符。

代码语言:javascript复制
function sqlalchemy.orm.attributes.set_attribute(instance: object, key: str, value: Any, initiator: AttributeEventToken | None = None) → None

设置属性的值,并触发历史事件。

无论直接应用于类的仪器如何,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来建立由 SQLAlchemy 理解的属性状态。

参数:

  • instance – 将要修改的对象
  • key – 属性的字符串名称
  • value – 要分配的值
  • initiator – 一个 Event 的实例,可能已从前一个事件侦听器传播。当在现有事件侦听器函数中使用 set_attribute() 函数时,其中提供了一个 Event 对象;该对象可用于跟踪事件链的来源。 自 1.2.3 版新功能。
代码语言:javascript复制
function sqlalchemy.orm.attributes.set_committed_value(instance, key, value)

设置没有历史事件的属性值。

取消任何先前存在的历史。值应为标量值(对于保存标量的属性)或可迭代对象(对于任何保存集合的属性)。

当惰性加载器触发并从数据库加载附加数据时,使用的是相同的基础方法。特别是,该方法可被应用代码使用,通过单独的查询加载了额外的属性或集合,然后可以将其附加到实例上,就像它是其原始加载状态的一部分一样。

代码语言:javascript复制
class sqlalchemy.orm.attributes.History

一个由添加、未更改和已删除值组成的 3 元组,表示在一个被检测的属性上发生的变化。

获取对象上特定属性的History对象的最简单方法是使用inspect()函数:

代码语言:javascript复制
from sqlalchemy import inspect

hist = inspect(myobject).attrs.myattribute.history

每个元组成员都是一个可迭代序列:

  • added - 添加到属性的项目的集合(第一个元组元素)。
  • unchanged - 在属性上没有更改的项目的集合(第二个元组元素)。
  • deleted - 从属性中删除的项目的集合(第三个元组元素)。

成员

added, deleted, empty(), has_changes(), non_added(), non_deleted(), sum(), unchanged

类签名

sqlalchemy.orm.Historybuiltins.tuple

代码语言:javascript复制
attribute added: Tuple[()] | List[Any]

字段编号 0 的别名

代码语言:javascript复制
attribute deleted: Tuple[()] | List[Any]

字段编号 2 的别名

代码语言:javascript复制
method empty() → bool

如果这个History没有更改并且没有现有的未更改状态,则返回 True。

代码语言:javascript复制
method has_changes() → bool

如果这个History有更改,则返回 True。

代码语言:javascript复制
method non_added() → Sequence[Any]

返回未更改 已删除的集合。

代码语言:javascript复制
method non_deleted() → Sequence[Any]

返回已添加 未更改的集合。

代码语言:javascript复制
method sum() → Sequence[Any]

返回已添加 未更改 已删除的集合。

代码语言:javascript复制
attribute unchanged: Tuple[()] | List[Any]

字段编号 1 的别名 _attribute(instance, key) | 删除属性的值,触发历史事件。 | | flag_dirty(instance) | 标记一个实例为“脏”状态,而不需要特定的属性名称。 | | flag_modified(instance, key) | 将实例上的属性标记为“已修改”。 | | get_attribute(instance, key) | 获取属性的值,触发任何所需的可调用函数。 | | get_history(obj, key[, passive]) | 返回给定对象和属性键的History记录。 | | History | 已添加、未更改和已删除值的 3 元组,表示在受监控属性上发生的更改。 | | init_collection(obj, key) | 初始化一个集合属性并返回集合适配器。 | | instance_state | 返回给定映射对象的InstanceState。 | | is_instrumented(instance, key) | 如果给定实例上的给定属性由 attributes 包进行了插装,则返回 True。 | | object_state(instance) | 给定一个对象,返回与该对象关联的InstanceState。 | | set_attribute(instance, key, value[, initiator]) | 设置属性的值,触发历史事件。 | | set_committed_value(instance, key, value) | 设置属性的值,不触发历史事件。 |

代码语言:javascript复制
function sqlalchemy.orm.util.object_state(instance: _T) → InstanceState[_T]

给定一个对象,返回与该对象关联的InstanceState

如果未配置映射,则引发sqlalchemy.orm.exc.UnmappedInstanceError

相同的功能可以通过inspect()函数获得,如下所示:

代码语言:javascript复制
inspect(instance)

使用检查系统将在实例不属于映射的情况下引发sqlalchemy.exc.NoInspectionAvailable

代码语言:javascript复制
function sqlalchemy.orm.attributes.del_attribute(instance: object, key: str) → None

删除属性的值,触发历史事件。

无论直接应用于类的插装如何,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来建立由 SQLAlchemy 理解的属性状态。

代码语言:javascript复制
function sqlalchemy.orm.attributes.get_attribute(instance: object, key: str) → Any

获取属性的值,触发任何所需的可调用函数。

无论直接应用于类的仪器,都可以使用此功能,即不需要描述符。自定义属性管理方案将需要使用此方法来使用 SQLAlchemy 所理解的属性状态。

代码语言:javascript复制
function sqlalchemy.orm.attributes.get_history(obj: object, key: str, passive: PassiveFlag = symbol('PASSIVE_OFF')) → History

返回给定对象和属性键的History记录。

这是给定属性的预刷新历史记录,每次Session刷新更改到当前数据库事务时都会重置它。

注意

首选使用AttributeState.historyAttributeState.load_history()访问器来检索实例属性的History

参数:

  • obj – 一个其类由属性包仪器化的对象。
  • key – 字符串属性名称。
  • passive – 如果值尚不存在,则指示属性的加载行为。这是一个位标志属性,默认为PASSIVE_OFF,表示应发出所有必要的 SQL。

另请参见

AttributeState.history

AttributeState.load_history() - 如果值在本地不存在,则使用加载器可调用检索历史。

代码语言:javascript复制
function sqlalchemy.orm.attributes.init_collection(obj: object, key: str) → CollectionAdapter

初始化一个集合属性并返回集合适配器。

此函数用于为先前未加载的属性提供直接访问集合内部。例如:

代码语言:javascript复制
collection_adapter = init_collection(someobject, 'elements')
for elem in values:
    collection_adapter.append_without_event(elem)

对于执行上述操作的更简单方法,请参见set_committed_value()

参数:

  • obj – 一个映射对象
  • key – 集合所在的字符串属性名称。
代码语言:javascript复制
function sqlalchemy.orm.attributes.flag_modified(instance: object, key: str) → None

将实例上的属性标记为“已修改”。

这会在实例上设置“已修改”标志,并为给定属性建立一个无条件的更改事件。属性必须具有值,否则会引发InvalidRequestError

要标记一个对象为“脏”,而不引用任何特定属性,以便在刷新时考虑到它,使用flag_dirty()调用。

另请参见

flag_dirty()

代码语言:javascript复制
function sqlalchemy.orm.attributes.flag_dirty(instance: object) → None

将实例标记为“脏”,而不提及任何特定属性。

这是一个特殊操作,允许对象通过刷新流程进行拦截,例如 SessionEvents.before_flush()。请注意,对于没有更改的对象,在刷新过程中不会发出任何 SQL,即使通过此方法标记为脏。但是,SessionEvents.before_flush() 处理程序将能够在 Session.dirty 集合中看到对象,并可能对其进行更改,然后这些更改将包含在发出的 SQL 中。

自 1.2 版新功能。

另请参阅

flag_modified()

代码语言:javascript复制
function sqlalchemy.orm.attributes.instance_state()

返回给定映射对象的 InstanceState

此函数是 object_state() 的内部版本。此处推荐使用 object_state() 和/或 inspect() 函数,因为它们会在给定对象未映射时各自发出信息丰富的异常。

代码语言:javascript复制
function sqlalchemy.orm.instrumentation.is_instrumented(instance, key)

如果给定实例上的给定属性由 attributes 包进行仪器化,则返回 True。

无论直接应用于类的仪器如何,都可以使用此函数,即不需要描述符。

代码语言:javascript复制
function sqlalchemy.orm.attributes.set_attribute(instance: object, key: str, value: Any, initiator: AttributeEventToken | None = None) → None

设置属性的值,并触发历史事件。

无论直接应用于类的仪器如何,都可以使用此函数,即不需要描述符。自定义属性管理方案将需要使用此方法来建立由 SQLAlchemy 理解的属性状态。

参数:

  • instance – 将要修改的对象
  • key – 属性的字符串名称
  • value – 要分配的值
  • initiator – 一个 Event 的实例,可能已从前一个事件侦听器传播。当在现有事件侦听器函数中使用 set_attribute() 函数时,其中提供了一个 Event 对象;该对象可用于跟踪事件链的来源。 自 1.2.3 版新功能。
代码语言:javascript复制
function sqlalchemy.orm.attributes.set_committed_value(instance, key, value)

设置没有历史事件的属性值。

取消任何先前存在的历史。值应为标量值(对于保存标量的属性)或可迭代对象(对于任何保存集合的属性)。

当惰性加载器触发并从数据库加载附加数据时,使用的是相同的基础方法。特别是,该方法可被应用代码使用,通过单独的查询加载了额外的属性或集合,然后可以将其附加到实例上,就像它是其原始加载状态的一部分一样。

代码语言:javascript复制
class sqlalchemy.orm.attributes.History

一个由添加、未更改和已删除值组成的 3 元组,表示在一个被检测的属性上发生的变化。

获取对象上特定属性的History对象的最简单方法是使用inspect()函数:

代码语言:javascript复制
from sqlalchemy import inspect

hist = inspect(myobject).attrs.myattribute.history

每个元组成员都是一个可迭代序列:

  • added - 添加到属性的项目的集合(第一个元组元素)。
  • unchanged - 在属性上没有更改的项目的集合(第二个元组元素)。
  • deleted - 从属性中删除的项目的集合(第三个元组元素)。

成员

added, deleted, empty(), has_changes(), non_added(), non_deleted(), sum(), unchanged

类签名

sqlalchemy.orm.Historybuiltins.tuple

代码语言:javascript复制
attribute added: Tuple[()] | List[Any]

字段编号 0 的别名

代码语言:javascript复制
attribute deleted: Tuple[()] | List[Any]

字段编号 2 的别名

代码语言:javascript复制
method empty() → bool

如果这个History没有更改并且没有现有的未更改状态,则返回 True。

代码语言:javascript复制
method has_changes() → bool

如果这个History有更改,则返回 True。

代码语言:javascript复制
method non_added() → Sequence[Any]

返回未更改 已删除的集合。

代码语言:javascript复制
method non_deleted() → Sequence[Any]

返回已添加 未更改的集合。

代码语言:javascript复制
method sum() → Sequence[Any]

返回已添加 未更改 已删除的集合。

代码语言:javascript复制
attribute unchanged: Tuple[()] | List[Any]

字段编号 1 的别名

0 人点赞