ORM 事件

ORM 包含各种可供订阅的钩子。

有关最常用的 ORM 事件的介绍,请参阅 使用事件跟踪查询、对象和 Session 更改 部分。有关事件系统的总体讨论,请参阅 事件。有关非 ORM 事件(例如关于连接和底层语句执行的事件),请参阅 核心事件

Session 事件

最基本的事件钩子在 ORM Session 对象级别可用。此处拦截的事项类型包括

  • 持久化操作 - ORM flush 进程将更改发送到数据库,可以使用在 flush 不同部分触发的事件进行扩展,以增强或修改发送到数据库的数据,或允许在发生持久化时发生其他事情。阅读更多关于持久化事件的信息,请访问 持久化事件

  • 对象生命周期事件 - 在对象被添加、持久化、从会话中删除时进行钩子。阅读更多关于这些的信息,请访问 对象生命周期事件

  • 执行事件 - 作为 2.0 风格 执行模型的一部分,针对 ORM 实体发出的所有 SELECT 语句,以及 flush 进程之外的批量 UPDATE 和 DELETE 语句,都通过 Session.execute() 方法使用 SessionEvents.do_orm_execute() 方法进行拦截。阅读更多关于此事件的信息,请访问 执行事件

请务必阅读 使用事件跟踪查询、对象和 Session 更改 章节,以了解这些事件的上下文。

对象名称 描述

SessionEvents

定义特定于 Session 生命周期事件。

class sqlalchemy.orm.SessionEvents

定义特定于 Session 生命周期事件。

例如:

from sqlalchemy import event
from sqlalchemy.orm import sessionmaker


def my_before_commit(session):
    print("before commit!")


Session = sessionmaker()

event.listen(Session, "before_commit", my_before_commit)

listen() 函数将接受 Session 对象以及 sessionmaker()scoped_session() 的返回结果。

此外,它还接受 Session 类,它将全局应用于所有 Session 实例。

参数:
  • raw=False

    当为 True 时,传递给适用于处理单个对象的事件监听器函数的 “target” 参数将是实例的 InstanceState 管理对象,而不是映射的实例本身。

    1.3.14 版本新增。

  • restore_load_context=False

    应用于 SessionEvents.loaded_as_persistent() 事件。在事件钩子完成时恢复对象的加载器上下文,以便正在进行的预加载操作继续适当地以对象为目标。如果未设置此标志,则在此事件中将对象移动到新的加载器上下文时,将发出警告。

    1.3.14 版本新增。

类签名

class sqlalchemy.orm.SessionEvents (sqlalchemy.event.Events)

method sqlalchemy.orm.SessionEvents.after_attach(session: Session, instance: _O) None

在实例附加到会话后执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_attach')
def receive_after_attach(session, instance):
    "listen for the 'after_attach' event"

    # ... (event handling logic) ...

这在添加、删除或合并后调用。

注意

从 0.8 版本开始,此事件在项目已完全与会话关联之后触发,这与之前的版本不同。对于需要对象尚未成为会话状态的事件处理程序(例如,在目标对象尚未完成时可能自动刷新的处理程序),请考虑新的 before_attach() 事件。

method sqlalchemy.orm.SessionEvents.after_begin(session: Session, transaction: SessionTransaction, connection: Connection) None

在连接上开始事务后执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_begin')
def receive_after_begin(session, transaction, connection):
    "listen for the 'after_begin' event"

    # ... (event handling logic) ...

注意

此事件在 Session 修改其自身内部状态的过程中调用。要在该钩子中调用 SQL 操作,请使用提供给事件的 Connection;不要直接使用 Session 运行 SQL 操作。

参数:
method sqlalchemy.orm.SessionEvents.after_bulk_delete(delete_context: _O) None

用于在调用旧版 Query.delete() 方法之后触发的事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_bulk_delete')
def receive_after_bulk_delete(delete_context):
    "listen for the 'after_bulk_delete' event"

    # ... (event handling logic) ...

# DEPRECATED calling style (pre-0.9, will be removed in a future release)
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_delete')
def receive_after_bulk_delete(session, query, query_context, result):
    "listen for the 'after_bulk_delete' event"

    # ... (event handling logic) ...

Changed in version 0.9: SessionEvents.after_bulk_delete() 事件现在接受参数 SessionEvents.after_bulk_delete.delete_context。对接受上面列出的旧参数签名的监听器函数的支持(标记为“已弃用”)将在未来的版本中删除。

旧版特性

SessionEvents.after_bulk_delete() 方法是 SQLAlchemy 2.0 中的旧版事件钩子。该事件不参与使用 delete()2.0 风格 调用,该调用在 使用自定义 WHERE 条件的 ORM UPDATE 和 DELETE 中进行了文档说明。对于 2.0 风格的使用,SessionEvents.do_orm_execute() 钩子将拦截这些调用。

参数:

delete_context

一个 “删除上下文” 对象,其中包含有关更新的详细信息,包括以下属性

  • session - 涉及的 Session

  • query - 调用此更新操作的 Query 对象。

  • result 作为批量 DELETE 操作的结果返回的 CursorResult

Changed in version 1.4: update_context 不再有关联的 QueryContext 对象。

method sqlalchemy.orm.SessionEvents.after_bulk_update(update_context: _O) None

用于在调用旧版 Query.update() 方法之后触发的事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_bulk_update')
def receive_after_bulk_update(update_context):
    "listen for the 'after_bulk_update' event"

    # ... (event handling logic) ...

# DEPRECATED calling style (pre-0.9, will be removed in a future release)
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_update')
def receive_after_bulk_update(session, query, query_context, result):
    "listen for the 'after_bulk_update' event"

    # ... (event handling logic) ...

Changed in version 0.9: SessionEvents.after_bulk_update() 事件现在接受参数 SessionEvents.after_bulk_update.update_context。对接受上面列出的旧参数签名的监听器函数的支持(标记为“已弃用”)将在未来的版本中删除。

旧版特性

SessionEvents.after_bulk_update() 方法是 SQLAlchemy 2.0 中的旧版事件钩子。该事件不参与使用 update()2.0 风格 调用,该调用在 使用自定义 WHERE 条件的 ORM UPDATE 和 DELETE 中进行了文档说明。对于 2.0 风格的使用,SessionEvents.do_orm_execute() 钩子将拦截这些调用。

参数:

update_context

一个 “更新上下文” 对象,其中包含有关更新的详细信息,包括以下属性

  • session - 涉及的 Session

  • query - 调用此更新操作的 Query 对象。

  • values 传递给 Query.update() 的 “values” 字典。

  • result 作为批量 UPDATE 操作的结果返回的 CursorResult

Changed in version 1.4: update_context 不再有关联的 QueryContext 对象。

method sqlalchemy.orm.SessionEvents.after_commit(session: Session) None

在提交发生后执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_commit')
def receive_after_commit(session):
    "listen for the 'after_commit' event"

    # ... (event handling logic) ...

注意

SessionEvents.after_commit() 钩子不是每次 flush 都执行,也就是说,Session 可以在事务范围内多次向数据库发出 SQL。为了拦截这些事件,请使用 SessionEvents.before_flush()SessionEvents.after_flush()SessionEvents.after_flush_postexec() 事件。

注意

当调用 SessionEvents.after_commit() 事件时,Session 不处于活动事务中,因此无法发出 SQL。要发出与每个事务对应的 SQL,请使用 SessionEvents.before_commit() 事件。

参数:

session – 目标 Session

method sqlalchemy.orm.SessionEvents.after_flush(session: Session, flush_context: UOWTransaction) None

在 flush 完成后但在 commit 被调用之前执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_flush')
def receive_after_flush(session, flush_context):
    "listen for the 'after_flush' event"

    # ... (event handling logic) ...

请注意,会话的状态仍处于 pre-flush 状态,即 ‘new’、‘dirty’ 和 ‘deleted’ 列表仍显示 pre-flush 状态以及实例属性的历史记录设置。

警告

此事件在 Session 发出 SQL 来修改数据库之后运行,但在它更改其内部状态以反映这些更改之前运行,包括将新插入的对象放入身份映射中。在此事件中发出的 ORM 操作(例如加载相关项)可能会产生新的身份映射条目,这些条目将立即被替换,有时会导致令人困惑的结果。从 1.3.9 版本开始,SQLAlchemy 将为此情况发出警告。

参数:
method sqlalchemy.orm.SessionEvents.after_flush_postexec(session: Session, flush_context: UOWTransaction) None

在刷新完成后以及后执行状态发生后执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_flush_postexec')
def receive_after_flush_postexec(session, flush_context):
    "listen for the 'after_flush_postexec' event"

    # ... (event handling logic) ...

此时,“new”、“dirty”和“deleted”列表将处于最终状态。实际的 commit() 可能已经发生,也可能尚未发生,这取决于刷新是否启动了自己的事务或参与了更大的事务。

参数:
method sqlalchemy.orm.SessionEvents.after_rollback(session: Session) None

在真正的 DBAPI 回滚发生后执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_rollback')
def receive_after_rollback(session):
    "listen for the 'after_rollback' event"

    # ... (event handling logic) ...

请注意,此事件仅在针对数据库发生实际回滚时触发 - 如果底层 DBAPI 事务已回滚,则不会在每次调用 Session.rollback() 方法时触发。 在许多情况下,Session 在此事件期间不会处于“active”状态,因为当前事务无效。 要获取在最外层回滚完成后处于活动状态的 Session,请使用 SessionEvents.after_soft_rollback() 事件,并检查 Session.is_active 标志。

参数:

session – 目标 Session

method sqlalchemy.orm.SessionEvents.after_soft_rollback(session: Session, previous_transaction: SessionTransaction) None

在任何回滚发生后执行,包括实际上未在 DBAPI 级别发出的“软”回滚。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_soft_rollback')
def receive_after_soft_rollback(session, previous_transaction):
    "listen for the 'after_soft_rollback' event"

    # ... (event handling logic) ...

这对应于嵌套回滚和外部回滚,即调用 DBAPI 的 rollback() 方法的最内层回滚,以及仅将其自身从事务堆栈中弹出的外层回滚调用。

给定的 Session 可用于在最外层回滚后调用 SQL 和 Session.query() 操作,方法是首先检查 Session.is_active 标志

@event.listens_for(Session, "after_soft_rollback")
def do_something(session, previous_transaction):
    if session.is_active:
        session.execute(text("select * from some_table"))
参数:
method sqlalchemy.orm.SessionEvents.after_transaction_create(session: Session, transaction: SessionTransaction) None

当新的 SessionTransaction 被创建时执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_transaction_create')
def receive_after_transaction_create(session, transaction):
    "listen for the 'after_transaction_create' event"

    # ... (event handling logic) ...

此事件与 SessionEvents.after_begin() 不同,因为它发生在每个 SessionTransaction 整体上,而不是在单个数据库连接上开始事务时。 它也为嵌套事务和子事务调用,并且始终与相应的 SessionEvents.after_transaction_end() 事件匹配(假设 Session 的正常操作)。

参数:
  • session – 目标 Session

  • transaction

    目标 SessionTransaction

    要检测这是否是最外层的 SessionTransaction,而不是“子事务”或 SAVEPOINT,请测试 SessionTransaction.parent 属性是否为 None

    @event.listens_for(session, "after_transaction_create")
    def after_transaction_create(session, transaction):
        if transaction.parent is None:
            ...  # work with top-level transaction

    要检测 SessionTransaction 是否为 SAVEPOINT,请使用 SessionTransaction.nested 属性

    @event.listens_for(session, "after_transaction_create")
    def after_transaction_create(session, transaction):
        if transaction.nested:
            ...  # work with SAVEPOINT transaction

method sqlalchemy.orm.SessionEvents.after_transaction_end(session: Session, transaction: SessionTransaction) None

SessionTransaction 的跨度结束时执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'after_transaction_end')
def receive_after_transaction_end(session, transaction):
    "listen for the 'after_transaction_end' event"

    # ... (event handling logic) ...

此事件与 SessionEvents.after_commit() 不同,因为它对应于所有正在使用的 SessionTransaction 对象,包括嵌套事务和子事务的对象,并且始终与相应的 SessionEvents.after_transaction_create() 事件匹配。

参数:
  • session – 目标 Session

  • transaction

    目标 SessionTransaction

    要检测这是否是最外层的 SessionTransaction,而不是“子事务”或 SAVEPOINT,请测试 SessionTransaction.parent 属性是否为 None

    @event.listens_for(session, "after_transaction_create")
    def after_transaction_end(session, transaction):
        if transaction.parent is None:
            ...  # work with top-level transaction

    要检测 SessionTransaction 是否为 SAVEPOINT,请使用 SessionTransaction.nested 属性

    @event.listens_for(session, "after_transaction_create")
    def after_transaction_end(session, transaction):
        if transaction.nested:
            ...  # work with SAVEPOINT transaction

method sqlalchemy.orm.SessionEvents.before_attach(session: Session, instance: _O) None

在实例附加到会话之前执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'before_attach')
def receive_before_attach(session, instance):
    "listen for the 'before_attach' event"

    # ... (event handling logic) ...

在添加、删除或合并导致对象成为会话一部分之前调用此方法。

method sqlalchemy.orm.SessionEvents.before_commit(session: Session) None

在调用 commit 之前执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'before_commit')
def receive_before_commit(session):
    "listen for the 'before_commit' event"

    # ... (event handling logic) ...

注意

SessionEvents.before_commit() 钩子不是每个刷新操作都会触发,也就是说,Session 可以在事务范围内多次向数据库发出 SQL。 要拦截这些事件,请使用 SessionEvents.before_flush()SessionEvents.after_flush()SessionEvents.after_flush_postexec() 事件。

参数:

session – 目标 Session

method sqlalchemy.orm.SessionEvents.before_flush(session: Session, flush_context: UOWTransaction, instances: Sequence[_O] | None) None

在刷新过程开始之前执行。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'before_flush')
def receive_before_flush(session, flush_context, instances):
    "listen for the 'before_flush' event"

    # ... (event handling logic) ...
参数:
  • session – 目标 Session

  • flush_context – 内部 UOWTransaction 对象,用于处理刷新的详细信息。

  • instances – 通常为 None,这是可以传递给 Session.flush() 方法的对象集合(请注意,不推荐使用此方法)。

method sqlalchemy.orm.SessionEvents.deleted_to_detached(session: Session, instance: _O) None

拦截特定对象的“已删除到分离”的转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'deleted_to_detached')
def receive_deleted_to_detached(session, instance):
    "listen for the 'deleted_to_detached' event"

    # ... (event handling logic) ...

当从会话中逐出已删除的对象时,将调用此事件。 发生这种情况的典型情况是,当提交 Session 的事务(在其中删除了对象)时; 对象从已删除状态移动到分离状态。

当调用 Session.expunge_all()Session.close() 事件时,以及如果通过 Session.expunge() 从其已删除状态单独逐出对象时,也会调用此事件。

method sqlalchemy.orm.SessionEvents.deleted_to_persistent(session: Session, instance: _O) None

拦截特定对象的“已删除到持久”的转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'deleted_to_persistent')
def receive_deleted_to_persistent(session, instance):
    "listen for the 'deleted_to_persistent' event"

    # ... (event handling logic) ...

仅当由于调用 Session.rollback() 而恢复在刷新中已成功删除的对象时,才会发生此转换。 在任何其他情况下都不会调用该事件。

method sqlalchemy.orm.SessionEvents.detached_to_persistent(session: Session, instance: _O) None

拦截特定对象的“分离到持久”的转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'detached_to_persistent')
def receive_detached_to_persistent(session, instance):
    "listen for the 'detached_to_persistent' event"

    # ... (event handling logic) ...

此事件是 SessionEvents.after_attach() 事件的专门化,仅针对此特定转换调用。 它通常在 Session.add() 调用期间以及 Session.delete() 调用期间调用(如果对象先前未与 Session 关联)(请注意,标记为“deleted”的对象在刷新进行之前仍保持“持久”状态)。

注意

如果对象由于调用 Session.delete() 而变为持久状态,则在调用此事件时,该对象尚未标记为已删除。 要检测已删除的对象,请检查发送到 SessionEvents.persistent_to_detached()deleted 标志,以便在刷新进行后触发事件,或者如果需要在刷新之前拦截已删除的对象,请检查 Session.deleted 集合(在 SessionEvents.before_flush() 事件中)。

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

attribute sqlalchemy.orm.SessionEvents.dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.SessionEventsDispatch object>

引用回到 _Dispatch 类。

与 _Dispatch._events 双向关联

method sqlalchemy.orm.SessionEvents.do_orm_execute(orm_execute_state: ORMExecuteState) None

拦截代表 ORM Session 对象执行的语句。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'do_orm_execute')
def receive_do_orm_execute(orm_execute_state):
    "listen for the 'do_orm_execute' event"

    # ... (event handling logic) ...

此事件针对从 Session.execute() 方法调用的所有顶级 SQL 语句以及相关方法(例如 Session.scalars()Session.scalar())调用。 从 SQLAlchemy 1.4 开始,所有通过 Session.execute() 方法以及相关方法 Session.scalars()Session.scalar() 等运行的 ORM 查询都将参与此事件。 此事件挂钩适用于在 ORM 刷新过程内部发出的查询,即 刷新 中描述的过程。

注意

SessionEvents.do_orm_execute() 事件钩子仅在 ORM 语句执行时触发,这意味着仅当通过 Session.execute() 以及 Session 对象上的类似方法调用时触发。它不会为仅由 SQLAlchemy Core 调用的语句触发,即直接使用 Connection.execute() 或源自 Engine 对象(不涉及任何 Session)的语句触发。要拦截所有 SQL 执行,无论是否使用 Core 或 ORM API,请参阅 ConnectionEvents 中的事件钩子,例如 ConnectionEvents.before_execute()ConnectionEvents.before_cursor_execute()

此外,此事件钩子适用于在 ORM flush 进程内部发出的查询,即 Flushing 中描述的进程;要拦截 flush 进程中的步骤,请参阅 持久化事件 以及 映射器级 Flush 事件 中描述的事件钩子。

此事件是一个 do_ 事件,意味着它有能力替换 Session.execute() 方法通常执行的操作。此事件的预期用途包括分片和结果缓存方案,这些方案可能寻求跨多个数据库连接调用相同的语句,返回从每个连接合并的结果,或者根本不调用语句,而是从缓存返回数据。

此钩子旨在取代在 SQLAlchemy 1.4 之前可以子类化的 Query._execute_and_instances 方法的使用。

参数:

orm_execute_stateORMExecuteState 的一个实例,其中包含有关当前执行的所有信息,以及用于派生其他常用信息的辅助函数。有关详细信息,请参阅该对象。

另请参阅

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

ORMExecuteState - 传递给 SessionEvents.do_orm_execute() 事件的对象,其中包含有关要调用的语句的所有信息。它还提供了一个接口来扩展当前语句、选项和参数,以及一个允许在任何时候以编程方式调用语句的选项。

ORM 查询事件 - 包括使用 SessionEvents.do_orm_execute() 的示例

Dogpile 缓存 - 如何将 Dogpile 缓存与 ORM Session 集成的示例,使用了 SessionEvents.do_orm_execute() 事件钩子。

水平分片 - 水平分片示例/扩展依赖于 SessionEvents.do_orm_execute() 事件钩子,以在多个后端调用 SQL 语句并返回合并的结果。

1.4 版本新增。

method sqlalchemy.orm.SessionEvents.loaded_as_persistent(session: Session, instance: _O) None

拦截特定对象的“加载为持久化”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'loaded_as_persistent')
def receive_loaded_as_persistent(session, instance):
    "listen for the 'loaded_as_persistent' event"

    # ... (event handling logic) ...

此事件在 ORM 加载过程中调用,并且与 InstanceEvents.load() 事件非常相似。但是,此处的事件可链接到 Session 类或实例,而不是映射器或类层次结构,并且与其他会话生命周期事件平滑集成。调用此事件时,对象保证存在于会话的身份映射中。

注意

此事件在加载器进程中调用,在 eager 加载器可能完成之前,并且对象的状态可能不完整。此外,对对象调用行级刷新操作会将对象置于新的加载器上下文中,从而干扰现有的加载上下文。有关使用 SessionEvents.restore_load_context 参数的背景信息,请参阅关于 InstanceEvents.load() 的注释,它与 InstanceEvents.restore_load_context 的工作方式相同,以解决这种情况。

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

method sqlalchemy.orm.SessionEvents.pending_to_persistent(session: Session, instance: _O) None

拦截特定对象的“pending 到 persistent”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'pending_to_persistent')
def receive_pending_to_persistent(session, instance):
    "listen for the 'pending_to_persistent' event"

    # ... (event handling logic) ...

此事件在 flush 进程中调用,并且类似于在 SessionEvents.after_flush() 事件中扫描 Session.new 集合。但是,在这种情况下,当调用事件时,对象已经移动到 persistent 状态。

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

method sqlalchemy.orm.SessionEvents.pending_to_transient(session: Session, instance: _O) None

拦截特定对象的“pending 到 transient”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'pending_to_transient')
def receive_pending_to_transient(session, instance):
    "listen for the 'pending_to_transient' event"

    # ... (event handling logic) ...

当尚未 flush 的 pending 对象从会话中逐出时,会发生这种不太常见的转换;当 Session.rollback() 方法回滚事务,或者当使用 Session.expunge() 方法时,可能会发生这种情况。

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

method sqlalchemy.orm.SessionEvents.persistent_to_deleted(session: Session, instance: _O) None

拦截特定对象的“persistent 到 deleted”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'persistent_to_deleted')
def receive_persistent_to_deleted(session, instance):
    "listen for the 'persistent_to_deleted' event"

    # ... (event handling logic) ...

当持久化对象的身份在 flush 期间从数据库中删除时,会调用此事件,但是该对象仍然与 Session 关联,直到事务完成。

如果事务回滚,则对象再次移动到 persistent 状态,并调用 SessionEvents.deleted_to_persistent() 事件。如果事务提交,则对象变为 detached,这将发出 SessionEvents.deleted_to_detached() 事件。

请注意,虽然 Session.delete() 方法是标记对象为已删除的主要公共接口,但许多对象由于级联规则而被删除,而级联规则并非总是在 flush 时确定。因此,在 flush 进行之前,无法捕获每个将被删除的对象。因此,SessionEvents.persistent_to_deleted() 事件在 flush 结束时调用。

method sqlalchemy.orm.SessionEvents.persistent_to_detached(session: Session, instance: _O) None

拦截特定对象的“persistent 到 detached”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'persistent_to_detached')
def receive_persistent_to_detached(session, instance):
    "listen for the 'persistent_to_detached' event"

    # ... (event handling logic) ...

当持久化对象从会话中逐出时,会调用此事件。有很多条件会导致这种情况发生,包括

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

  • deleted – 布尔值。如果为 True,则表示此对象移动到 detached 状态是因为它被标记为已删除并已 flush。

method sqlalchemy.orm.SessionEvents.persistent_to_transient(session: Session, instance: _O) None

拦截特定对象的“persistent 到 transient”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'persistent_to_transient')
def receive_persistent_to_transient(session, instance):
    "listen for the 'persistent_to_transient' event"

    # ... (event handling logic) ...

当已 flush 的 pending 对象从会话中逐出时,会发生这种不太常见的转换;当 Session.rollback() 方法回滚事务时,可能会发生这种情况。

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

method sqlalchemy.orm.SessionEvents.transient_to_pending(session: Session, instance: _O) None

拦截特定对象的“transient 到 pending”转换。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeSessionClassOrObject, 'transient_to_pending')
def receive_transient_to_pending(session, instance):
    "listen for the 'transient_to_pending' event"

    # ... (event handling logic) ...

此事件是 SessionEvents.after_attach() 事件的特化,仅针对此特定转换调用。它通常在 Session.add() 调用期间调用。

参数:
  • session – 目标 Session

  • instance – 正在操作的 ORM 映射实例。

映射器事件

映射器事件钩子涵盖与单个或多个 Mapper 对象相关的事项,这些对象是将用户定义的类映射到 Table 对象的中心配置对象。在 Mapper 级别发生的事件类型包括

对象名称 描述

MapperEvents

定义特定于映射的事件。

class sqlalchemy.orm.MapperEvents

定义特定于映射的事件。

例如:

from sqlalchemy import event


def my_before_insert_listener(mapper, connection, target):
    # execute a stored procedure upon INSERT,
    # apply the value to the row to be inserted
    target.calculated_value = connection.execute(
        text("select my_special_function(%d)" % target.special_number)
    ).scalar()


# associate the listener function with SomeClass,
# to execute during the "before_insert" hook
event.listen(SomeClass, "before_insert", my_before_insert_listener)

可用目标包括

  • 映射类

  • 映射类的未映射超类(使用 propagate=True 标志)

  • Mapper 对象

  • Mapper 类本身表示监听所有映射器。

映射器事件提供了进入映射器关键部分的钩子,包括与对象检测、对象加载和对象持久化相关的部分。特别是,持久化方法 MapperEvents.before_insert()MapperEvents.before_update() 是增强要持久化的状态的常用位置 - 但是,这些方法在几个重要的限制下运行。建议用户评估 SessionEvents.before_flush()SessionEvents.after_flush() 方法,作为在 flush 期间应用其他数据库状态的更灵活和用户友好的钩子。

当使用 MapperEvents 时,listen() 函数可以使用多个修饰符。

参数:
  • propagate=False – 当为 True 时,事件监听器应应用于所有继承的映射器和/或继承类的映射器,以及作为此监听器目标的任何映射器。

  • raw=False – 当为 True 时,传递给适用事件监听器函数的 “target” 参数将是实例的 InstanceState 管理对象,而不是映射的实例本身。

  • retval=False

    当为 True 时,用户定义的事件函数必须具有返回值,其目的是控制后续事件传播,或以其他方式更改映射器正在进行的操作。可能的返回值是

    • sqlalchemy.orm.interfaces.EXT_CONTINUE - 正常继续事件处理。

    • sqlalchemy.orm.interfaces.EXT_STOP - 取消链中所有后续事件处理程序。

    • 其他值 - 由特定监听器指定的返回值。

类签名

sqlalchemy.orm.MapperEvents (sqlalchemy.event.Events)

方法 sqlalchemy.orm.MapperEvents.after_configured() None

在一系列映射器配置完成后调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'after_configured')
def receive_after_configured():
    "listen for the 'after_configured' event"

    # ... (event handling logic) ...

MapperEvents.after_configured() 事件在每次调用 configure_mappers() 函数后,并在该函数完成其工作之后被调用。configure_mappers() 通常在首次使用映射时自动调用,并且在每次有新的映射器可用并检测到新的映射器使用时也会调用。

此事件与 MapperEvents.mapper_configured() 事件形成对比,后者在配置操作进行时针对每个映射器调用;与该事件不同,当此事件被调用时,所有交叉配置(例如,反向引用)也将可用于任何待处理的映射器。 另请注意与 MapperEvents.before_configured() 的对比,后者在一系列映射器配置之前被调用。

此事件只能应用于 Mapper 类,而不是应用于单个映射或映射类。它仅针对所有映射作为一个整体调用

from sqlalchemy.orm import Mapper


@event.listens_for(Mapper, "after_configured")
def go(): ...

理论上,此事件每个应用程序调用一次,但实际上在每次新的映射器受到 configure_mappers() 调用的影响时都会调用。 如果在现有映射已被使用后构建了新的映射,则此事件可能会再次被调用。 为了确保特定事件仅被调用一次且不再调用,可以应用 once=True 参数(0.9.4 版本新增)

from sqlalchemy.orm import mapper


@event.listens_for(mapper, "after_configured", once=True)
def go(): ...
方法 sqlalchemy.orm.MapperEvents.after_delete(mapper: Mapper[_O], connection: Connection, target: _O) None

在发出与该实例对应的 DELETE 语句后接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'after_delete')
def receive_after_delete(mapper, connection, target):
    "listen for the 'after_delete' event"

    # ... (event handling logic) ...

注意

此事件适用于 session flush 操作,并且适用于 ORM-Enabled INSERT, UPDATE, and DELETE statements 中描述的 ORM DML 操作。 要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

此事件用于在给定的连接上发出额外的 SQL 语句,以及执行与删除事件相关的应用程序特定记账操作。

该事件通常在先前步骤中一次性发出 DELETE 语句后,针对同一类的一批对象调用。

警告

映射器级别的 flush 事件仅允许非常有限的操作,仅限于对正在操作的行本地的属性,并允许在给定的 Connection 上发出任何 SQL。 请完整阅读 映射器级别 Flush 事件 中的注释,以获取有关使用这些方法的指南;通常,对于一般的 flush 时更改,应首选 SessionEvents.before_flush() 方法。

参数:
  • mapper – 作为此事件目标的 Mapper

  • connection – 用于为此实例发出 DELETE 语句的 Connection。 这提供了访问此实例特定于目标数据库的当前事务的句柄。

  • target – 正在删除的映射实例。 如果事件配置了 raw=True,则这将改为与该实例关联的 InstanceState 状态管理对象。

返回值:

此事件不支持返回值。

另请参阅

持久化事件

方法 sqlalchemy.orm.MapperEvents.after_insert(mapper: Mapper[_O], connection: Connection, target: _O) None

在发出与该实例对应的 INSERT 语句后接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'after_insert')
def receive_after_insert(mapper, connection, target):
    "listen for the 'after_insert' event"

    # ... (event handling logic) ...

注意

此事件适用于 session flush 操作,并且适用于 ORM-Enabled INSERT, UPDATE, and DELETE statements 中描述的 ORM DML 操作。 要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

此事件用于在 INSERT 发生后修改实例上的仅 Python 状态,以及在给定的连接上发出额外的 SQL 语句。

该事件通常在先前步骤中一次性发出 INSERT 语句后,针对同一类的一批对象调用。 在极少数情况下,如果这不可取,则可以使用 batch=False 配置 Mapper 对象,这将导致将批处理实例分解为单独的(且性能较差的)事件->持久化->事件步骤。

警告

映射器级别的 flush 事件仅允许非常有限的操作,仅限于对正在操作的行本地的属性,并允许在给定的 Connection 上发出任何 SQL。 请完整阅读 映射器级别 Flush 事件 中的注释,以获取有关使用这些方法的指南;通常,对于一般的 flush 时更改,应首选 SessionEvents.before_flush() 方法。

参数:
  • mapper – 作为此事件目标的 Mapper

  • connection – 用于为此实例发出 INSERT 语句的 Connection。 这提供了访问此实例特定于目标数据库的当前事务的句柄。

  • target – 正在持久化的映射实例。 如果事件配置了 raw=True,则这将改为与该实例关联的 InstanceState 状态管理对象。

返回值:

此事件不支持返回值。

另请参阅

持久化事件

方法 sqlalchemy.orm.MapperEvents.after_mapper_constructed(mapper: Mapper[_O], class_: Type[_O]) None

Mapper 完全构建后接收类和映射器。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'after_mapper_constructed')
def receive_after_mapper_constructed(mapper, class_):
    "listen for the 'after_mapper_constructed' event"

    # ... (event handling logic) ...

此事件在 Mapper 的初始构造函数完成后调用。 这发生在 MapperEvents.instrument_class() 事件之后,以及在 Mapper 完成对其参数的初始传递以生成其 MapperProperty 对象集合之后,这些对象可以通过 Mapper.get_property() 方法和 Mapper.iterate_properties 属性访问。

此事件与 MapperEvents.before_mapper_configured() 事件不同,后者在 Mapper 的构造函数中调用,而不是在 registry.configure() 进程中调用。 目前,此事件是唯一适用于希望响应此 Mapper 的构建来创建其他映射类的处理程序,这将是 registry.configure() 下次运行时同一配置步骤的一部分。

2.0.2 版本新增。

另请参阅

对象版本控制 - 一个示例,说明如何使用 MapperEvents.before_mapper_configured() 事件来创建新的映射器以记录对象的更改审计历史记录。

方法 sqlalchemy.orm.MapperEvents.after_update(mapper: Mapper[_O], connection: Connection, target: _O) None

在发出与该实例对应的 UPDATE 语句后接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'after_update')
def receive_after_update(mapper, connection, target):
    "listen for the 'after_update' event"

    # ... (event handling logic) ...

注意

此事件适用于 session flush 操作,并且适用于 ORM-Enabled INSERT, UPDATE, and DELETE statements 中描述的 ORM DML 操作。 要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

此事件用于在 UPDATE 发生后修改实例上的仅 Python 状态,以及在给定的连接上发出额外的 SQL 语句。

对于所有标记为“脏”的实例,即使那些对其基于列的属性没有净更改的实例,以及没有执行 UPDATE 语句的实例,也会调用此方法。 当任何基于列的属性调用了“set attribute”操作或修改了任何集合时,对象将被标记为脏。 如果在更新时,没有基于列的属性有任何净更改,则不会发出 UPDATE 语句。 这意味着发送到 MapperEvents.after_update() 的实例不能保证已发出 UPDATE 语句。

要检测对象上基于列的属性是否具有净更改,并因此导致 UPDATE 语句,请使用 object_session(instance).is_modified(instance, include_collections=False)

该事件通常在先前步骤中一次性发出 UPDATE 语句后,针对同一类的一批对象调用。 在极少数情况下,如果这不可取,则可以使用 batch=False 配置 Mapper,这将导致将批处理实例分解为单独的(且性能较差的)事件->持久化->事件步骤。

警告

映射器级别的 flush 事件仅允许非常有限的操作,仅限于对正在操作的行本地的属性,并允许在给定的 Connection 上发出任何 SQL。 请完整阅读 映射器级别 Flush 事件 中的注释,以获取有关使用这些方法的指南;通常,对于一般的 flush 时更改,应首选 SessionEvents.before_flush() 方法。

参数:
  • mapper – 作为此事件目标的 Mapper

  • connection – 用于为此实例发出 UPDATE 语句的 Connection。 这提供了访问此实例特定于目标数据库的当前事务的句柄。

  • target – 正在持久化的映射实例。 如果事件配置了 raw=True,则这将改为与该实例关联的 InstanceState 状态管理对象。

返回值:

此事件不支持返回值。

另请参阅

持久化事件

方法 sqlalchemy.orm.MapperEvents.before_configured() None

在一系列映射器配置之前调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'before_configured')
def receive_before_configured():
    "listen for the 'before_configured' event"

    # ... (event handling logic) ...

MapperEvents.before_configured() 事件在每次调用 configure_mappers() 函数后,并在该函数开始工作之前被调用。configure_mappers() 通常在首次使用映射时自动调用,并且在每次有新的映射器可用并检测到新的映射器使用时也会调用。

此事件只能应用于 Mapper 类,而不是应用于单个映射或映射类。它仅针对所有映射作为一个整体调用

from sqlalchemy.orm import Mapper


@event.listens_for(Mapper, "before_configured")
def go(): ...

此事件与 MapperEvents.after_configured() 形成对比,后者在一系列映射器配置完成后被调用,以及与 MapperEvents.before_mapper_configured()MapperEvents.mapper_configured() 形成对比,后两者都是针对每个映射器调用的。

理论上,此事件每个应用程序调用一次,但实际上在每次新的映射器将受到 configure_mappers() 调用的影响时都会调用。 如果在现有映射已被使用后构建了新的映射,则此事件可能会再次被调用。 为了确保特定事件仅被调用一次且不再调用,可以应用 once=True 参数(0.9.4 版本新增)

from sqlalchemy.orm import mapper


@event.listens_for(mapper, "before_configured", once=True)
def go(): ...
方法 sqlalchemy.orm.MapperEvents.before_delete(mapper: Mapper[_O], connection: Connection, target: _O) None

在发出与该实例对应的 DELETE 语句之前接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'before_delete')
def receive_before_delete(mapper, connection, target):
    "listen for the 'before_delete' event"

    # ... (event handling logic) ...

注意

此事件适用于 session flush 操作,并且适用于 ORM-Enabled INSERT, UPDATE, and DELETE statements 中描述的 ORM DML 操作。 要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

此事件用于在给定的连接上发出额外的 SQL 语句,以及执行与删除事件相关的应用程序特定记账操作。

该事件通常在稍后步骤中一次性发出 DELETE 语句之前,针对同一类的一批对象调用。

警告

映射器级别的 flush 事件仅允许非常有限的操作,仅限于对正在操作的行本地的属性,并允许在给定的 Connection 上发出任何 SQL。 请完整阅读 映射器级别 Flush 事件 中的注释,以获取有关使用这些方法的指南;通常,对于一般的 flush 时更改,应首选 SessionEvents.before_flush() 方法。

参数:
  • mapper – 作为此事件目标的 Mapper

  • connection – 用于为此实例发出 DELETE 语句的 Connection。 这提供了访问此实例特定于目标数据库的当前事务的句柄。

  • target – 正在删除的映射实例。 如果事件配置了 raw=True,则这将改为与该实例关联的 InstanceState 状态管理对象。

返回值:

此事件不支持返回值。

另请参阅

持久化事件

方法 sqlalchemy.orm.MapperEvents.before_insert(mapper: Mapper[_O], connection: Connection, target: _O) None

在发出与该实例对应的 INSERT 语句之前接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'before_insert')
def receive_before_insert(mapper, connection, target):
    "listen for the 'before_insert' event"

    # ... (event handling logic) ...

注意

此事件适用于 session flush 操作,并且适用于 ORM-Enabled INSERT, UPDATE, and DELETE statements 中描述的 ORM DML 操作。 要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

此事件用于在 INSERT 发生之前修改实例上的本地、非对象相关属性,以及在给定的连接上发出额外的 SQL 语句。

该事件通常在稍后步骤中一次性发出 INSERT 语句之前,针对同一类的一批对象调用。 在极少数情况下,如果这不可取,则可以使用 batch=False 配置 Mapper 对象,这将导致将批处理实例分解为单独的(且性能较差的)事件->持久化->事件步骤。

警告

映射器级别的 flush 事件仅允许非常有限的操作,仅限于对正在操作的行本地的属性,并允许在给定的 Connection 上发出任何 SQL。 请完整阅读 映射器级别 Flush 事件 中的注释,以获取有关使用这些方法的指南;通常,对于一般的 flush 时更改,应首选 SessionEvents.before_flush() 方法。

参数:
  • mapper – 作为此事件目标的 Mapper

  • connection – 用于为此实例发出 INSERT 语句的 Connection。 这提供了访问此实例特定于目标数据库的当前事务的句柄。

  • target – 正在持久化的映射实例。 如果事件配置了 raw=True,则这将改为与该实例关联的 InstanceState 状态管理对象。

返回值:

此事件不支持返回值。

另请参阅

持久化事件

方法 sqlalchemy.orm.MapperEvents.before_mapper_configured(mapper: Mapper[_O], class_: Type[_O]) None

在即将配置特定映射器之前调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'before_mapper_configured')
def receive_before_mapper_configured(mapper, class_):
    "listen for the 'before_mapper_configured' event"

    # ... (event handling logic) ...

此事件旨在允许在配置步骤中跳过特定映射器,方法是返回 interfaces.EXT_SKIP 符号,该符号指示 configure_mappers() 调用应在当前配置运行中跳过此特定映射器(或映射器层次结构,如果使用 propagate=True)。 当跳过一个或多个映射器时,“新映射器”标志将保持设置状态,这意味着 configure_mappers() 函数将在使用映射器时继续调用,以继续尝试配置所有可用的映射器。

与其他配置级别事件 MapperEvents.before_configured()MapperEvents.after_configured()MapperEvents.mapper_configured() 相比,MapperEvents.before_mapper_configured() 事件在注册 retval=True 参数时提供了有意义的返回值。

1.3 版本新增。

例如:

from sqlalchemy.orm import EXT_SKIP

Base = declarative_base()

DontConfigureBase = declarative_base()


@event.listens_for(
    DontConfigureBase,
    "before_mapper_configured",
    retval=True,
    propagate=True,
)
def dont_configure(mapper, cls):
    return EXT_SKIP
方法 sqlalchemy.orm.MapperEvents.before_update(mapper: Mapper[_O], connection: Connection, target: _O) None

在发出与对象实例对应的 UPDATE 语句之前,接收该对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'before_update')
def receive_before_update(mapper, connection, target):
    "listen for the 'before_update' event"

    # ... (event handling logic) ...

注意

此事件适用于 session flush 操作,并且适用于 ORM-Enabled INSERT, UPDATE, and DELETE statements 中描述的 ORM DML 操作。 要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

此事件用于在 UPDATE 发生之前修改实例上本地的、非对象相关的属性,以及在给定的连接上发出额外的 SQL 语句。

此方法为所有标记为“脏”的实例调用,即使是那些基于列的属性没有净更改的实例。当任何基于列的属性调用了“set attribute”操作或任何集合被修改时,对象都会被标记为脏。 如果在更新时,没有基于列的属性有任何净更改,则不会发出 UPDATE 语句。 这意味着发送到 MapperEvents.before_update() 的实例并不能保证会发出 UPDATE 语句,尽管您可以通过修改属性以使其存在净值更改来影响此处的结果。

要检测对象上基于列的属性是否具有净更改,以及是否因此将生成 UPDATE 语句,请使用 object_session(instance).is_modified(instance, include_collections=False)

此事件通常为同一类的一批对象调用,然后在后续步骤中一次性发出它们的 UPDATE 语句。 在极其罕见的情况下,如果不需要这样做,则可以使用 batch=False 配置 Mapper,这将导致将批量的实例分解为单独的(且性能较差的)事件->持久化->事件步骤。

警告

映射器级别的 flush 事件仅允许非常有限的操作,仅限于对正在操作的行本地的属性,并允许在给定的 Connection 上发出任何 SQL。 请完整阅读 映射器级别 Flush 事件 中的注释,以获取有关使用这些方法的指南;通常,对于一般的 flush 时更改,应首选 SessionEvents.before_flush() 方法。

参数:
  • mapper – 作为此事件目标的 Mapper

  • connection – 用于为此实例发出 UPDATE 语句的 Connection。 这提供了访问特定于此实例的目标数据库上当前事务的句柄。

  • target – 正在持久化的映射实例。 如果事件配置了 raw=True,则这将是与实例关联的 InstanceState 状态管理对象。

返回值:

此事件不支持返回值。

另请参阅

持久化事件

属性 sqlalchemy.orm.MapperEvents.dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.MapperEventsDispatch object>

引用回到 _Dispatch 类。

与 _Dispatch._events 双向关联

方法 sqlalchemy.orm.MapperEvents.instrument_class(mapper: Mapper[_O], class_: Type[_O]) None

当首次构造映射器时,在将工具化应用于映射类之前,接收一个类。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'instrument_class')
def receive_instrument_class(mapper, class_):
    "listen for the 'instrument_class' event"

    # ... (event handling logic) ...

此事件是映射器构造的最早阶段。 映射器的大多数属性尚未初始化。 要在初始映射器构造中接收事件,其中基本状态可用,例如 Mapper.attrs 集合,MapperEvents.after_mapper_constructed() 事件可能是更好的选择。

此监听器可以应用于整个 Mapper 类,也可以应用于任何未映射的类,该类充当将被映射的类的基类(使用 propagate=True 标志)

Base = declarative_base()


@event.listens_for(Base, "instrument_class", propagate=True)
def on_new_class(mapper, cls_):
    "..."
参数:
  • mapper – 作为此事件目标的 Mapper

  • class_ – 映射的类。

方法 sqlalchemy.orm.MapperEvents.mapper_configured(mapper: Mapper[_O], class_: Type[_O]) None

当特定的映射器在 configure_mappers() 调用的范围内完成其自身配置时调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'mapper_configured')
def receive_mapper_configured(mapper, class_):
    "listen for the 'mapper_configured' event"

    # ... (event handling logic) ...

MapperEvents.mapper_configured() 事件针对在 configure_mappers() 函数遍历当前未配置的映射器列表时遇到的每个映射器调用。 configure_mappers() 通常在首次使用映射时自动调用,以及每次有新的映射器可用并检测到新的映射器使用时调用。

当事件被调用时,映射器应处于其最终状态,但不包括可能从其他映射器调用的反向引用; 它们可能仍在配置操作中挂起。 通过 relationship.back_populates 参数配置的双向关系完全可用,因为这种关系样式不依赖于其他可能未配置的映射器来知道它们的存在。

对于保证所有映射器都准备就绪的事件,包括仅在其他映射上定义的反向引用,请使用 MapperEvents.after_configured() 事件; 此事件仅在所有已知映射都已完全配置后调用。

MapperEvents.before_configured()MapperEvents.after_configured() 不同,MapperEvents.mapper_configured() 事件是为每个映射器/类单独调用的,并且映射器本身被传递给事件。 它也为特定的映射器只调用一次。 因此,该事件对于那些受益于在特定映射器基础上仅调用一次的配置步骤非常有用,这些步骤不需要“反向引用”配置已经准备就绪。

参数:
  • mapper – 作为此事件目标的 Mapper

  • class_ – 映射的类。

实例事件

实例事件侧重于 ORM 映射实例的构造,包括当它们被实例化为 瞬态 对象,当它们从数据库加载并成为 持久化 对象,以及当对象上发生数据库刷新或过期操作时。

对象名称 描述

InstanceEvents

定义特定于对象生命周期的事件。

sqlalchemy.orm.InstanceEvents

定义特定于对象生命周期的事件。

例如:

from sqlalchemy import event


def my_load_listener(target, context):
    print("on load!")


event.listen(SomeClass, "load", my_load_listener)

可用目标包括

  • 映射类

  • 映射类的未映射超类(使用 propagate=True 标志)

  • Mapper 对象

  • Mapper 类本身表示监听所有映射器。

实例事件与映射器事件密切相关,但更具体于实例及其工具化,而不是其持久化系统。

当使用 InstanceEvents 时,listen() 函数有几个修饰符可用。

参数:
  • propagate=False – 当为 True 时,事件监听器应应用于所有继承类以及作为此监听器目标的类。

  • raw=False – 当为 True 时,传递给适用事件监听器函数的“target”参数将是实例的 InstanceState 管理对象,而不是映射实例本身。

  • restore_load_context=False

    适用于 InstanceEvents.load()InstanceEvents.refresh() 事件。 在事件挂钩完成时恢复对象的加载器上下文,以便正在进行的预加载操作继续适当地以对象为目标。 如果对象从这些事件之一中移动到新的加载器上下文,并且未设置此标志,则会发出警告。

    1.3.14 版本新增。

类签名

sqlalchemy.orm.InstanceEvents (sqlalchemy.event.Events)

属性 sqlalchemy.orm.InstanceEvents.dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstanceEventsDispatch object>

引用回到 _Dispatch 类。

与 _Dispatch._events 双向关联

方法 sqlalchemy.orm.InstanceEvents.expire(target: _O, attrs: Iterable[str] | None) None

在其属性或某些子集已过期后,接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'expire')
def receive_expire(target, attrs):
    "listen for the 'expire' event"

    # ... (event handling logic) ...

“keys”是属性名称的列表。 如果为 None,则整个状态已过期。

参数:
  • target – 映射的实例。 如果事件配置了 raw=True,则这将是与实例关联的 InstanceState 状态管理对象。

  • attrs – 已过期的属性名称序列,如果所有属性都已过期,则为 None。

方法 sqlalchemy.orm.InstanceEvents.first_init(manager: ClassManager[_O], cls: Type[_O]) None

当调用特定映射的第一个实例时调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'first_init')
def receive_first_init(manager, cls):
    "listen for the 'first_init' event"

    # ... (event handling logic) ...

当首次为特定类调用该类的 __init__ 方法时,将调用此事件。 该事件在 __init__ 实际进行之前以及在调用 InstanceEvents.init() 事件之前调用。

方法 sqlalchemy.orm.InstanceEvents.init(target: _O, args: Any, kwargs: Any) None

当调用实例的构造函数时接收实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'init')
def receive_init(target, args, kwargs):
    "listen for the 'init' event"

    # ... (event handling logic) ...

此方法仅在用户端构造对象期间调用,与对象的构造函数(例如,其 __init__ 方法)结合使用。 从数据库加载对象时不会调用它; 请参阅 InstanceEvents.load() 事件,以便拦截数据库加载。

该事件在调用对象的实际 __init__ 构造函数之前调用。 可以就地修改 kwargs 字典,以影响传递给 __init__ 的内容。

参数:
  • target – 映射的实例。 如果事件配置了 raw=True,则这将是与实例关联的 InstanceState 状态管理对象。

  • args – 传递给 __init__ 方法的位置参数。 这作为元组传递,目前是不可变的。

  • kwargs – 传递给 __init__ 方法的关键字参数。 此结构可以就地更改。

方法 sqlalchemy.orm.InstanceEvents.init_failure(target: _O, args: Any, kwargs: Any) None

当实例的构造函数已被调用并引发异常时,接收实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'init_failure')
def receive_init_failure(target, args, kwargs):
    "listen for the 'init_failure' event"

    # ... (event handling logic) ...

此方法仅在用户端构造对象期间调用,与对象的构造函数(例如,其 __init__ 方法)结合使用。 从数据库加载对象时不会调用它。

该事件在捕获到 __init__ 方法引发的异常后调用。 在调用事件后,原始异常会向外重新引发,以便对象的构造仍然引发异常。 实际引发的异常和堆栈跟踪应存在于 sys.exc_info() 中。

参数:
  • target – 映射的实例。 如果事件配置了 raw=True,则这将是与实例关联的 InstanceState 状态管理对象。

  • args – 传递给 __init__ 方法的位置参数。

  • kwargs – 传递给 __init__ 方法的关键字参数。

方法 sqlalchemy.orm.InstanceEvents.load(target: _O, context: QueryContext) None

在通过 __new__ 创建对象实例之后,以及在初始属性填充发生之后,接收该对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'load')
def receive_load(target, context):
    "listen for the 'load' event"

    # ... (event handling logic) ...

这通常发生在基于传入的结果行创建实例时,并且对于该实例的生命周期仅调用一次。

警告

在结果行加载期间,当处理为此实例接收的第一行时,将调用此事件。 当将预加载与面向集合的属性一起使用时,尚未发生为了加载后续集合项而要加载/处理的其他行。 这既会影响集合不会完全加载,也会影响如果在此事件处理程序中发生操作,该操作为对象发出另一个数据库加载操作,则对象的“加载上下文”可能会更改并干扰仍在进行的现有预加载器。

可能导致事件处理程序中“加载上下文”更改的示例包括但不一定限于

  • 访问不属于该行的延迟属性,将触发“undefer”操作并刷新对象

  • 访问不属于该行的连接继承子类上的属性,将触发刷新操作。

从 SQLAlchemy 1.3.14 开始,当发生这种情况时会发出警告。 InstanceEvents.restore_load_context 选项可用于事件以防止此警告; 这将确保在调用事件后,对象的现有加载上下文得到维护

@event.listens_for(SomeClass, "load", restore_load_context=True)
def on_load(instance, context):
    instance.some_unloaded_attribute

在 1.3.14 版本中变更: 添加了 InstanceEvents.restore_load_contextSessionEvents.restore_load_context 标志,这些标志适用于“加载时”事件,这将确保在事件挂钩完成时恢复对象的加载上下文; 如果对象的加载上下文在未设置此标志的情况下更改,则会发出警告。

InstanceEvents.load() 事件也可以通过名为 reconstructor() 的类方法装饰器格式使用。

参数:
  • target – 映射的实例。如果事件配置了 raw=True,则此参数将是与该实例关联的 InstanceState 状态管理对象。

  • context – 与当前正在进行的 Query 相对应的 QueryContext。如果加载不对应于 Query,例如在 Session.merge() 期间,则此参数可能为 None

method sqlalchemy.orm.InstanceEvents.pickle(target: _O, state_dict: _InstanceDict) None

当对象实例的关联状态被 pickle 序列化时接收该实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'pickle')
def receive_pickle(target, state_dict):
    "listen for the 'pickle' event"

    # ... (event handling logic) ...
参数:
  • target – 映射的实例。如果事件配置了 raw=True,则此参数将是与该实例关联的 InstanceState 状态管理对象。

  • state_dict – 由 __getstate__ 返回的字典,其中包含要进行 pickle 序列化的状态。

method sqlalchemy.orm.InstanceEvents.refresh(target: _O, context: QueryContext, attrs: Iterable[str] | None) None

在一个或多个属性已从查询中刷新后接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'refresh')
def receive_refresh(target, context, attrs):
    "listen for the 'refresh' event"

    # ... (event handling logic) ...

将此事件与 InstanceEvents.load() 方法进行对比,后者在对象首次从查询加载时被调用。

注意

此事件在加载器进程中被调用,先于 eager loaders 完成之前,并且对象的状态可能不完整。此外,对对象调用行级刷新操作会将对象置于新的加载器上下文中,从而干扰现有的加载上下文。有关使用 InstanceEvents.restore_load_context 参数以解决此场景的背景信息,请参阅关于 InstanceEvents.load() 的注释。

参数:
  • target – 映射的实例。如果事件配置了 raw=True,则此参数将是与该实例关联的 InstanceState 状态管理对象。

  • context – 与当前正在进行的 Query 相对应的 QueryContext

  • attrs – 已填充的属性名称序列,如果所有列映射的非延迟属性都被填充,则为 None。

method sqlalchemy.orm.InstanceEvents.refresh_flush(target: _O, flush_context: UOWTransaction, attrs: Iterable[str] | None) None

在持久化对象状态期间,当一个或多个包含列级默认值或 onupdate 处理程序的属性被刷新后,接收对象实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'refresh_flush')
def receive_refresh_flush(target, flush_context, attrs):
    "listen for the 'refresh_flush' event"

    # ... (event handling logic) ...

此事件与 InstanceEvents.refresh() 相同,不同之处在于它在工作单元 flush 进程中被调用,并且仅包含具有列级默认值或 onupdate 处理程序的非主键列,包括 Python 可调用对象以及服务器端默认值和触发器,这些值可以通过 RETURNING 子句获取。

注意

虽然 InstanceEvents.refresh_flush() 事件是为 INSERT 和 UPDATE 的对象触发的,但该事件主要面向 UPDATE 过程;INSERT 操作也可以触发此事件,这主要是一个内部工件,请注意,INSERT 行的主键列在此事件中被显式省略。为了拦截对象新 INSERT 的状态,SessionEvents.pending_to_persistent()MapperEvents.after_insert() 是更好的选择。

参数:
  • target – 映射的实例。如果事件配置了 raw=True,则此参数将是与该实例关联的 InstanceState 状态管理对象。

  • flush_context – 内部 UOWTransaction 对象,用于处理 flush 的详细信息。

  • attrs – 已填充的属性名称序列。

method sqlalchemy.orm.InstanceEvents.unpickle(target: _O, state_dict: _InstanceDict) None

在对象实例的关联状态被 unpickle 反序列化后接收该实例。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass, 'unpickle')
def receive_unpickle(target, state_dict):
    "listen for the 'unpickle' event"

    # ... (event handling logic) ...
参数:
  • target – 映射的实例。如果事件配置了 raw=True,则此参数将是与该实例关联的 InstanceState 状态管理对象。

  • state_dict – 发送到 __setstate__ 的字典,其中包含已进行 pickle 序列化的状态字典。

属性事件

当 ORM 映射对象的各个属性上发生某些事情时,会触发属性事件。这些事件构成了诸如 自定义验证函数 以及 反向引用处理程序 等功能的基础。

另请参阅

更改属性行为

对象名称 描述

AttributeEvents

为对象属性定义事件。

class sqlalchemy.orm.AttributeEvents

为对象属性定义事件。

这些通常在目标类的类绑定描述符上定义。

例如,要注册一个侦听器,该侦听器将接收 AttributeEvents.append() 事件

from sqlalchemy import event


@event.listens_for(MyClass.collection, "append", propagate=True)
def my_append_listener(target, value, initiator):
    print("received append event for target: %s" % target)

AttributeEvents.retval 标志传递给 listen()listens_for() 时,侦听器可以选择返回值的可能修改版本,如下所示,使用 AttributeEvents.set() 事件进行说明

def validate_phone(target, value, oldvalue, initiator):
    "Strip non-numeric characters from a phone number"

    return re.sub(r"\D", "", value)


# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, "set", validate_phone, retval=True)

像上面这样的验证函数也可以引发异常,例如 ValueError 以中止操作。

当将侦听器应用于也具有映射子类的映射类时,AttributeEvents.propagate 标志也很重要,例如在使用映射器继承模式时

@event.listens_for(MySuperClass.attr, "set", propagate=True)
def receive_set(target, value, initiator):
    print("value set: %s" % target)

以下是 listen()listens_for() 函数可用的所有修饰符的完整列表。

参数:
  • active_history=False – 当为 True 时,表示 “set” 事件希望无条件地接收被替换的 “旧” 值,即使这需要触发数据库加载。请注意,active_history 也可以通过 column_property()relationship() 直接设置。

  • propagate=False – 当为 True 时,侦听器函数不仅将为给定的类属性建立,而且还将为该类的所有当前子类以及该类的所有未来子类上的同名属性建立,使用额外的侦听器来侦听 instrumentation 事件。

  • raw=False – 当为 True 时,事件的 “target” 参数将是 InstanceState 管理对象,而不是映射的实例本身。

  • retval=False – 当为 True 时,用户定义的事件侦听必须从函数返回 “value” 参数。这使侦听函数有机会更改最终用于 “set” 或 “append” 事件的值。

类签名

class sqlalchemy.orm.AttributeEvents (sqlalchemy.event.Events)

method sqlalchemy.orm.AttributeEvents.append(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) _T | None

接收集合追加事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'append')
def receive_append(target, value, initiator):
    "listen for the 'append' event"

    # ... (event handling logic) ...

当每个元素被追加到集合时,将为每个元素调用 append 事件。这发生在单项追加以及 “批量替换” 操作中。

参数:
  • target – 接收事件的对象实例。如果侦听器注册了 raw=True,则这将是 InstanceState 对象。

  • value – 要追加的值。如果此侦听器注册了 retval=True,则侦听器函数必须返回此值,或返回替换它的新值。

  • initiatorEvent 的实例,表示事件的启动。可以由反向引用处理程序从其原始值修改,以控制链式事件传播,以及检查有关事件源的信息。

  • key

    当使用设置为 True 的 AttributeEvents.include_key 参数建立事件时,这将是操作中使用的键,例如 collection[some_key_or_index] = value。如果未使用 AttributeEvents.include_key 设置事件,则根本不会将此参数传递给事件;这是为了与不包含 key 参数的现有事件处理程序向后兼容。

    2.0 版本新增。

返回值:

如果事件注册了 retval=True,则应返回给定值或新的有效值。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

AttributeEvents.bulk_replace()

method sqlalchemy.orm.AttributeEvents.append_wo_mutation(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) None

接收集合追加事件,其中集合实际上未被修改。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'append_wo_mutation')
def receive_append_wo_mutation(target, value, initiator):
    "listen for the 'append_wo_mutation' event"

    # ... (event handling logic) ...

此事件与 AttributeEvents.append() 的不同之处在于,当对象已存在于目标集合中时,对于去重集合(如集合和字典)会触发此事件。该事件没有返回值,并且给定对象的标识无法更改。

当集合已通过反向引用事件修改时,此事件用于将对象级联到 Session 中。

参数:
  • target – 接收事件的对象实例。如果侦听器注册了 raw=True,则这将是 InstanceState 对象。

  • value – 如果对象尚未存在于集合中,则将追加的值。

  • initiatorEvent 的实例,表示事件的启动。可以由反向引用处理程序从其原始值修改,以控制链式事件传播,以及检查有关事件源的信息。

  • key

    当使用设置为 True 的 AttributeEvents.include_key 参数建立事件时,这将是操作中使用的键,例如 collection[some_key_or_index] = value。如果未使用 AttributeEvents.include_key 设置事件,则根本不会将此参数传递给事件;这是为了与不包含 key 参数的现有事件处理程序向后兼容。

    2.0 版本新增。

返回值:

此事件未定义返回值。

1.4.15 版本新增。

method sqlalchemy.orm.AttributeEvents.bulk_replace(target: _O, values: Iterable[_T], initiator: Event, *, keys: Iterable[EventConstants] | None = None) None

接收集合 “批量替换” 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'bulk_replace')
def receive_bulk_replace(target, values, initiator):
    "listen for the 'bulk_replace' event"

    # ... (event handling logic) ...

当一系列值即将进入批量集合设置操作时,将为这些值调用此事件,可以在将这些值视为 ORM 对象之前就地修改它们。这是一个 “早期挂钩”,在批量替换例程尝试协调哪些对象已存在于集合中以及哪些对象将被净替换操作删除之前运行。

通常,此方法与 AttributeEvents.append() 事件结合使用。当同时使用这两个事件时,请注意,批量替换操作将为所有新项目调用 AttributeEvents.append() 事件,即使在为整个集合调用 AttributeEvents.bulk_replace() 之后也是如此。为了确定 AttributeEvents.append() 事件是否是批量替换的一部分,请使用符号 attributes.OP_BULK_REPLACE 测试传入的 initiator

from sqlalchemy.orm.attributes import OP_BULK_REPLACE


@event.listens_for(SomeObject.collection, "bulk_replace")
def process_collection(target, values, initiator):
    values[:] = [_make_value(value) for value in values]


@event.listens_for(SomeObject.collection, "append", retval=True)
def process_collection(target, value, initiator):
    # make sure bulk_replace didn't already do it
    if initiator is None or initiator.op is not OP_BULK_REPLACE:
        return _make_value(value)
    else:
        return value

1.2 版本新增。

参数:
  • target – 接收事件的对象实例。如果侦听器注册了 raw=True,则这将是 InstanceState 对象。

  • value – 要设置的值的序列(例如,列表)。处理程序可以就地修改此列表。

  • initiatorEvent 的实例,表示事件的启动。

  • keys

    当使用设置为 True 的 AttributeEvents.include_key 参数建立事件时,这将是操作中使用的键序列,通常仅用于字典更新。如果未使用 AttributeEvents.include_key 设置事件,则根本不会将此参数传递给事件;这是为了与不包含 key 参数的现有事件处理程序向后兼容。

    2.0 版本新增。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

attribute sqlalchemy.orm.AttributeEvents.dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.AttributeEventsDispatch object>

引用回到 _Dispatch 类。

与 _Dispatch._events 双向关联

method sqlalchemy.orm.AttributeEvents.dispose_collection(target: _O, collection: Collection[Any], collection_adapter: CollectionAdapter) None

接收 “集合 dispose” 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'dispose_collection')
def receive_dispose_collection(target, collection, collection_adapter):
    "listen for the 'dispose_collection' event"

    # ... (event handling logic) ...

当替换集合时,会为基于集合的属性触发此事件,即

u1.addresses.append(a1)

u1.addresses = [a2, a3]  # <- old collection is disposed

接收到的旧集合将包含其先前的内容。

在 1.2 版本中变更:传递给 AttributeEvents.dispose_collection() 的集合现在将在 dispose 之前保持其内容完整;以前,集合将为空。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

method sqlalchemy.orm.AttributeEvents.init_collection(target: _O, collection: Type[Collection[Any]], collection_adapter: CollectionAdapter) None

接收 “集合 init” 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'init_collection')
def receive_init_collection(target, collection, collection_adapter):
    "listen for the 'init_collection' event"

    # ... (event handling logic) ...

此事件为基于集合的属性触发,当为一个空白属性首次生成初始“空集合”时,以及当集合被新集合替换时(例如通过 set 事件)。

例如,假设 User.addresses 是一个基于关系的集合,则此事件在此处触发

u1 = User()
u1.addresses.append(a1)  #  <- new collection

以及在替换操作期间触发

u1.addresses = [a2, a3]  #  <- new collection
参数:
  • target – 接收事件的对象实例。如果监听器使用 raw=True 注册,则这将是 InstanceState 对象。

  • collection – 新的集合。这将始终从指定为 relationship.collection_class 的内容生成,并且始终为空。

  • collection_adapterCollectionAdapter,它将调解对集合的内部访问。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

AttributeEvents.init_scalar() - 此事件的“标量”版本。

method sqlalchemy.orm.AttributeEvents.init_scalar(target: _O, value: _T, dict_: Dict[Any, Any]) None

接收标量 “init” 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'init_scalar')
def receive_init_scalar(target, value, dict_):
    "listen for the 'init_scalar' event"

    # ... (event handling logic) ...

当访问未初始化、未持久化的标量属性时,例如读取时,将调用此事件

x = my_object.some_attribute

当未初始化属性发生这种情况时,ORM 的默认行为是返回值 None;请注意,这与 Python 通常引发 AttributeError 的行为不同。此处的事件可用于自定义实际返回的值,前提是事件监听器将镜像在 Core Column 对象上配置的默认生成器。

由于 Column 上的默认生成器也可能生成变化的值(例如时间戳),因此 AttributeEvents.init_scalar() 事件处理程序也可用于设置新返回的值,以便核心级别的默认生成函数仅在访问非持久化对象上的属性时有效触发一次。通常,当访问未初始化的属性时,不会对对象的状态进行任何更改(早期版本的 SQLAlchemy 实际上会更改对象的状态)。

如果列上的默认生成器返回特定的常量,则可以使用如下处理程序

SOME_CONSTANT = 3.1415926


class MyClass(Base):
    # ...

    some_attribute = Column(Numeric, default=SOME_CONSTANT)


@event.listens_for(
    MyClass.some_attribute, "init_scalar", retval=True, propagate=True
)
def _init_some_attribute(target, dict_, value):
    dict_["some_attribute"] = SOME_CONSTANT
    return SOME_CONSTANT

上面,我们将属性 MyClass.some_attribute 初始化为 SOME_CONSTANT 的值。上面的代码包括以下功能

  • 通过在给定的 dict_ 中设置值 SOME_CONSTANT,我们指示此值将持久化到数据库。这取代了在 Column 的默认生成器中使用 SOME_CONSTANTactive_column_defaults.py 示例在 属性 Instrumentation 中给出,说明了对变化的默认值(例如时间戳生成器)使用相同的方法。在此特定示例中,严格来说没有必要这样做,因为在任何情况下 SOME_CONSTANT 都将是 INSERT 语句的一部分。

  • 通过建立 retval=True 标志,我们从函数返回的值将由属性 getter 返回。如果没有此标志,则假定该事件是被动观察者,并且我们函数的返回值将被忽略。

  • 如果映射的类包含继承子类,并且这些子类也需要使用此事件监听器,则 propagate=True 标志非常重要。如果没有此标志,继承子类将不会使用我们的事件处理程序。

在上面的示例中,当我们对给定的 dict_ 应用我们的值时,属性 set 事件 AttributeEvents.set() 以及 validates 提供的相关验证功能不会被调用。要使这些事件响应我们新生成的值而被调用,请将该值作为正常的属性设置操作应用于给定对象

SOME_CONSTANT = 3.1415926


@event.listens_for(
    MyClass.some_attribute, "init_scalar", retval=True, propagate=True
)
def _init_some_attribute(target, dict_, value):
    # will also fire off attribute set events
    target.some_attribute = SOME_CONSTANT
    return SOME_CONSTANT

当设置了多个监听器时,值的生成将从一个监听器“链接”到下一个监听器,方法是将前一个指定 retval=True 的监听器返回的值作为下一个监听器的 value 参数传递。

参数:
  • target – 接收事件的对象实例。如果监听器使用 raw=True 注册,则这将是 InstanceState 对象。

  • value – 在调用此事件监听器之前要返回的值。此值最初为 None 值,但是,如果存在多个监听器,则将是先前事件处理程序函数的返回值。

  • dict_ – 此映射对象的属性字典。这通常是对象的 __dict__,但在所有情况下,它都表示属性系统用于获取此属性的实际值的目标。将值放入此字典的效果是该值将用于工作单元生成的 INSERT 语句中。

另请参阅

AttributeEvents.init_collection() - 此事件的集合版本

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

属性 Instrumentation - 请参阅 active_column_defaults.py 示例。

method sqlalchemy.orm.AttributeEvents.modified(target: _O, initiator: Event) None

接收 “modified” 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'modified')
def receive_modified(target, initiator):
    "listen for the 'modified' event"

    # ... (event handling logic) ...

当使用 flag_modified() 函数在属性上触发 modify 事件,而未设置任何特定值时,将触发此事件。

1.2 版本新增。

参数:
  • target – 接收事件的对象实例。如果监听器使用 raw=True 注册,则这将是 InstanceState 对象。

  • initiatorEvent 的实例,表示事件的启动。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

method sqlalchemy.orm.AttributeEvents.remove(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) None

接收集合 remove 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'remove')
def receive_remove(target, value, initiator):
    "listen for the 'remove' event"

    # ... (event handling logic) ...
参数:
  • target – 接收事件的对象实例。如果监听器使用 raw=True 注册,则这将是 InstanceState 对象。

  • value – 要删除的值。

  • initiatorEvent 的实例,表示事件的启动。可能会被反向引用处理程序从其原始值修改,以便控制链式事件传播。

  • key

    当使用设置为 True 的 AttributeEvents.include_key 参数建立事件时,这将是在操作中使用的键,例如 del collection[some_key_or_index]。如果未使用 AttributeEvents.include_key 设置事件,则参数根本不会传递给事件;这是为了允许与不包含 key 参数的现有事件处理程序向后兼容。

    2.0 版本新增。

返回值:

此事件未定义返回值。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

method sqlalchemy.orm.AttributeEvents.set(target: _O, value: _T, oldvalue: _T, initiator: Event) None

接收标量 set 事件。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeClass.some_attribute, 'set')
def receive_set(target, value, oldvalue, initiator):
    "listen for the 'set' event"

    # ... (event handling logic) ...
参数:
  • target – 接收事件的对象实例。如果监听器使用 raw=True 注册,则这将是 InstanceState 对象。

  • value – 要设置的值。如果此监听器使用 retval=True 注册,则监听器函数必须返回此值,或替换它的新值。

  • oldvalue – 要替换的先前值。这也可能是符号 NEVER_SETNO_VALUE。如果监听器使用 active_history=True 注册,则如果现有值当前未加载或已过期,则将从数据库加载属性的先前值。

  • initiatorEvent 的实例,表示事件的启动。可能会被反向引用处理程序从其原始值修改,以便控制链式事件传播。

返回值:

如果事件注册了 retval=True,则应返回给定值或新的有效值。

另请参阅

AttributeEvents - 关于侦听器选项(例如传播到子类)的背景信息。

查询事件

对象名称 描述

QueryEvents

表示 Query 对象的构造中的事件。

class sqlalchemy.orm.QueryEvents

表示 Query 对象的构造中的事件。

旧版特性

自 SQLAlchemy 2.0 起,QueryEvents 事件方法已过时,仅适用于直接使用 Query 对象。它们不适用于 2.0 风格 语句。对于拦截和修改 2.0 风格 ORM 用法的事件,请使用 SessionEvents.do_orm_execute() 钩子。

QueryEvents 钩子现在已被 SessionEvents.do_orm_execute() 事件钩子取代。

类签名

class sqlalchemy.orm.QueryEvents (sqlalchemy.event.Events)

method sqlalchemy.orm.QueryEvents.before_compile(query: Query) None

Query 对象被组合成核心 Select 对象之前,接收该对象。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeQuery, 'before_compile')
def receive_before_compile(query):
    "listen for the 'before_compile' event"

    # ... (event handling logic) ...

Deprecated since version 1.4: QueryEvents.before_compile() 事件已被功能更强大的 SessionEvents.do_orm_execute() 钩子取代。在 1.4 版本中,QueryEvents.before_compile() 事件不再用于 ORM 级别的属性加载,例如延迟或过期属性的加载以及关系加载器。请参阅 ORM 查询事件 中的新示例,这些示例说明了拦截和修改 ORM 查询以实现添加任意过滤条件的最常见目的的新方法。

此事件旨在允许更改给定的查询

@event.listens_for(Query, "before_compile", retval=True)
def no_deleted(query):
    for desc in query.column_descriptions:
        if desc["type"] is User:
            entity = desc["entity"]
            query = query.filter(entity.deleted == False)
    return query

通常应使用设置了 retval=True 参数来监听该事件,以便可以返回修改后的查询。

默认情况下,如果 QueryEvents.before_compile() 事件返回新的 Query 对象,则该事件将不允许“baked”查询缓存查询。这会影响 baked query 扩展的直接使用,以及其在关系的延迟加载器和迫切加载器中的操作。为了重新建立正在缓存的查询,请应用添加 bake_ok 标志的事件

@event.listens_for(Query, "before_compile", retval=True, bake_ok=True)
def my_event(query):
    for desc in query.column_descriptions:
        if desc["type"] is User:
            entity = desc["entity"]
            query = query.filter(entity.deleted == False)
    return query

bake_ok 设置为 True 时,事件钩子将仅被调用一次,而不会为正在缓存的特定查询的后续调用而调用。

New in version 1.3.11: - 向 QueryEvents.before_compile() 事件添加了 “bake_ok” 标志,并且如果未设置此标志,则禁止事件处理程序返回新的 Query 对象时,通过 “baked” 扩展进行缓存。

method sqlalchemy.orm.QueryEvents.before_compile_delete(query: Query, delete_context: BulkDelete) None

允许在 Query.delete() 中修改 Query 对象。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeQuery, 'before_compile_delete')
def receive_before_compile_delete(query, delete_context):
    "listen for the 'before_compile_delete' event"

    # ... (event handling logic) ...

Deprecated since version 1.4: QueryEvents.before_compile_delete() 事件已被功能更强大的 SessionEvents.do_orm_execute() 钩子取代。

QueryEvents.before_compile() 事件一样,此事件应配置为 retval=True,并返回修改后的 Query 对象,如下所示

@event.listens_for(Query, "before_compile_delete", retval=True)
def no_deleted(query, delete_context):
    for desc in query.column_descriptions:
        if desc["type"] is User:
            entity = desc["entity"]
            query = query.filter(entity.deleted == False)
    return query
参数:
  • queryQuery 实例;这也是给定 “delete context” 对象的 .query 属性。

  • delete_context – “delete context” 对象,它与 QueryEvents.after_bulk_delete.delete_context 中描述的对象类型相同。

New in version 1.2.17.

method sqlalchemy.orm.QueryEvents.before_compile_update(query: Query, update_context: BulkUpdate) None

允许在 Query.update() 中修改 Query 对象。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeQuery, 'before_compile_update')
def receive_before_compile_update(query, update_context):
    "listen for the 'before_compile_update' event"

    # ... (event handling logic) ...

Deprecated since version 1.4: QueryEvents.before_compile_update() 事件已被功能更强大的 SessionEvents.do_orm_execute() 钩子取代。

QueryEvents.before_compile() 事件一样,如果要使用该事件来更改 Query 对象,则应将其配置为 retval=True,并返回修改后的 Query 对象,如下所示

@event.listens_for(Query, "before_compile_update", retval=True)
def no_deleted(query, update_context):
    for desc in query.column_descriptions:
        if desc["type"] is User:
            entity = desc["entity"]
            query = query.filter(entity.deleted == False)

            update_context.values["timestamp"] = datetime.datetime.now(
                datetime.UTC
            )
    return query

“update context” 对象的 .values 字典也可以像上面所示那样就地修改。

参数:
  • queryQuery 实例;这也是给定 “update context” 对象的 .query 属性。

  • update_context – “update context” 对象,与 QueryEvents.after_bulk_update.update_context 中描述的对象类型相同。该对象在 UPDATE 上下文中具有 .values 属性,该属性是一个字典,其中包含传递给 Query.update() 的参数。可以修改此字典以更改生成的 UPDATE 语句的 VALUES 子句。

New in version 1.2.17.

attribute sqlalchemy.orm.QueryEvents.dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.QueryEventsDispatch object>

引用回到 _Dispatch 类。

与 _Dispatch._events 双向关联

Instrumentation Events

定义了 SQLAlchemy 的类 instrumentation 系统。

此模块通常不直接对用户应用程序可见,但定义了 ORM 交互性的大部分。

instrumentation.py 负责注册最终用户类以进行状态跟踪。它与 state.py 和 attributes.py 紧密交互,后者分别建立每个实例和每个类属性的 instrumentation。

可以使用 sqlalchemy.ext.instrumentation 模块在每个类或全局基础上自定义类 instrumentation 系统,该模块提供了构建和指定备用 instrumentation 形式的方法。

对象名称 描述

InstrumentationEvents

与类 instrumentation 事件相关的事件。

class sqlalchemy.orm.InstrumentationEvents

与类 instrumentation 事件相关的事件。

此处的侦听器支持针对任何新式类建立,即任何作为 “type” 子类的对象。然后,将针对该类的事件触发事件。如果将 “propagate=True” 标志传递给 event.listen(),则该事件也将为该类的子类触发。

Python 内置的 type 也被接受为目标,当使用时,它会产生为所有类发出事件的效果。

请注意,此处的 “propagate” 标志默认为 True,这与其他类级别事件(默认为 False)不同。这意味着当在超类上建立侦听器时,新的子类也将成为这些事件的主题。

类签名

class sqlalchemy.orm.InstrumentationEvents (sqlalchemy.event.Events)

method sqlalchemy.orm.InstrumentationEvents.attribute_instrument(cls: ClassManager[_O], key: _KT, inst: _O) None

当属性被 instrumented 时调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeBaseClass, 'attribute_instrument')
def receive_attribute_instrument(cls, key, inst):
    "listen for the 'attribute_instrument' event"

    # ... (event handling logic) ...
method sqlalchemy.orm.InstrumentationEvents.class_instrument(cls: ClassManager[_O]) None

在给定的类被 instrumented 后调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeBaseClass, 'class_instrument')
def receive_class_instrument(cls):
    "listen for the 'class_instrument' event"

    # ... (event handling logic) ...

要获取 ClassManager,请使用 manager_of_class()

method sqlalchemy.orm.InstrumentationEvents.class_uninstrument(cls: ClassManager[_O]) None

在给定的类被 uninstrumented 之前调用。

示例参数形式

from sqlalchemy import event


@event.listens_for(SomeBaseClass, 'class_uninstrument')
def receive_class_uninstrument(cls):
    "listen for the 'class_uninstrument' event"

    # ... (event handling logic) ...

要获取 ClassManager,请使用 manager_of_class()

attribute sqlalchemy.orm.InstrumentationEvents.dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstrumentationEventsDispatch object>

引用回到 _Dispatch 类。

与 _Dispatch._events 双向关联