ORM 事件

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

有关最常用 ORM 事件的介绍,请参见 使用事件跟踪查询、对象和会话变化 一节。事件系统总体上在 事件 中进行了讨论。非 ORM 事件(例如,与连接和低级语句执行有关的事件)在 核心事件 中进行了描述。

会话事件

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

  • 持久化操作 - 将更改发送到数据库的 ORM 刷新过程可以使用在刷新过程的不同阶段触发的事件进行扩展,以增强或修改发送到数据库的数据,或允许在持久化发生时执行其他操作。有关持久化事件的更多信息,请参见 持久化事件

  • 对象生命周期事件 - 在对象被添加到会话、持久化到会话或从会话中删除时触发的钩子。有关这些事件的更多信息,请参见 对象生命周期事件

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

请务必阅读 使用事件跟踪查询、对象和会话变化 一章以了解这些事件的上下文。

对象名称 描述

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: The SessionEvents.after_bulk_delete() 事件现在接受参数 SessionEvents.after_bulk_delete.delete_context. 对接受上述作为“已弃用”的先前参数签名的监听器函数的支持将在未来版本中删除。

遗留功能

从 SQLAlchemy 2.0 开始,SessionEvents.after_bulk_delete() 方法是一个遗留的事件钩子。该事件不参与使用在 ORM UPDATE 和 DELETE 具有自定义 WHERE 条件 中记录的 delete()2.0 风格 调用。对于 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: The SessionEvents.after_bulk_update() 事件现在接受参数 SessionEvents.after_bulk_update.update_context. 对接受上述作为“已弃用”的先前参数签名的监听器函数的支持将在未来版本中删除。

遗留功能

从 SQLAlchemy 2.0 开始,SessionEvents.after_bulk_update() 方法是一个遗留的事件钩子。该事件不参与使用在 ORM UPDATE 和 DELETE 具有自定义 WHERE 条件 中记录的 update()2.0 风格 调用。对于 2.0 风格的使用,SessionEvents.do_orm_execute() 钩子将拦截这些调用。

参数::

update_context

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

  • session - 所涉及的 Session

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

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

  • 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) ...

注意

The SessionEvents.after_commit() hook is not per-flush, that is, the Session can emit SQL to the database many times within the scope of a transaction. For interception of these events, use the SessionEvents.before_flush(), SessionEvents.after_flush(), or SessionEvents.after_flush_postexec() events.

注意

The Session is not in an active transaction when the SessionEvents.after_commit() event is invoked, and therefore can not emit SQL. To emit SQL corresponding to every transaction, use the SessionEvents.before_commit() event.

参数::

session – The target 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) ...

请注意,会话的状态仍然处于 flush 之前,即“new”、“dirty”和“deleted”列表仍然显示 flush 之前的状态以及实例属性上的历史记录设置。

警告

此事件在 Session 已向数据库发出 SQL 以修改数据库之后运行,但在它更改其内部状态以反映这些更改之前运行,包括新插入的对象被放置到身份映射中。从版本 1.3.9 开始,SQLAlchemy 会对这种情况发出警告。

参数::
  • session – The target Session.

  • flush_context – Internal UOWTransaction object which handles the details of the flush.

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

在 flush 完成后,以及 post-exec 状态发生后执行。

示例参数形式

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() 可能发生也可能不发生,具体取决于 flush 是否启动了自己的事务或参与了更大的事务。

参数::
  • session – The target Session.

  • flush_context – Internal UOWTransaction object which handles the details of the flush.

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) ...

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

参数::

session – The target 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 可以在最外层回滚后首先检查 Session.is_active 标志后用于调用 SQL 和 Session.query() 操作。

@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 是最外层的 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 是最外层的 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

在调用提交之前执行。

示例参数形式

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 关联(请注意,标记为“已删除”的对象将保持“持久化”状态,直到刷新进行)。

注意

如果该对象在调用 Session.delete() 时变为持久化,则在调用此事件时,该对象不会被标记为已删除。 若要检测已删除的对象,请在刷新进行后检查发送到 SessionEvents.persistent_to_detached()deleted 标志,或者在 SessionEvents.before_flush() 事件中检查 Session.deleted 集合,如果需要在刷新之前拦截已删除的对象。

参数::
  • 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 刷新过程中内部发出的查询,即 刷新 中描述的过程;要拦截刷新过程中的步骤,请参阅 持久化事件 以及 映射器级别的刷新事件 中描述的事件钩子。

此事件是一个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 类或实例,而不是映射器或类层次结构,并且与其他会话生命周期事件无缝集成。当此事件被调用时,该对象保证存在于会话的标识映射中。

注意

此事件在加载器过程内部被调用,在急切加载器完成之前,并且对象的 state 可能不完整。此外,在对象上调用行级刷新操作将把对象置于新的加载器上下文中,干扰现有的加载上下文。有关使用 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

拦截特定对象的“待处理到持久化”转换。

示例参数形式

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) ...

此事件在刷新过程中被调用,类似于在 SessionEvents.after_flush() 事件中扫描 Session.new 集合。但是,在这种情况下,当事件被调用时,对象已经被移动到持久化状态。

参数::
  • session – 目标 Session

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

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

拦截特定对象的“待处理到瞬态”转换。

示例参数形式

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) ...

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

参数::
  • session – 目标 Session

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

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

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

示例参数形式

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) ...

当持久对象的标识在冲洗操作中从数据库中删除时,会触发此事件,但该对象仍然与 Session 关联,直到事务完成。

如果事务回滚,该对象将再次移至持久状态,并调用 SessionEvents.deleted_to_persistent() 事件。如果事务提交,该对象将变为分离状态,这将发出 SessionEvents.deleted_to_detached() 事件。

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

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

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

示例参数形式

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,则表示该对象移至分离状态,因为它被标记为已删除并已冲洗。

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

拦截特定对象的“持久到瞬态”转换。

示例参数形式

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) ...

这种不太常见的转换发生在已冲洗的挂起对象从会话中驱逐时;当 Session.rollback() 方法回滚事务时,就会发生这种情况。

参数::
  • session – 目标 Session

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

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

拦截特定对象的“瞬态到挂起”转换。

示例参数形式

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() 方法,作为更灵活和用户友好的钩子,用于在刷新期间应用额外的数据库状态。

使用 MapperEvents 时,listen() 函数提供了一些修饰符。

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

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

  • retval=False

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

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

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

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

类签名

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

method 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() 事件进行对比,后者是在配置操作进行时针对每个映射器调用的;与该事件不同,当调用此事件时,所有交叉配置(例如 backrefs)也将对任何待处理的映射器可用。还与 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():
    # ...
method 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) ...

注意

此事件 **仅** 适用于 会话刷新操作,并且 **不** 适用于 ORM 启用的 INSERT、UPDATE 和 DELETE 语句 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

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

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

警告

映射器级刷新事件只允许执行 **非常有限的操作**,这些操作仅限于正在操作的行上的本地属性,并且允许在给定的 Connection 上发出任何 SQL。 **请仔细阅读** 映射器级刷新事件 中的说明,了解有关使用这些方法的指南;通常,SessionEvents.before_flush() 方法应优先用于一般刷新更改。

参数::
  • mapperMapper,它是此事件的目标。

  • connectionConnection,用于为该实例发出 DELETE 语句。这提供了一个句柄,指向特定于该实例的目标数据库上的当前事务。

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

返回值:

此事件不支持返回值。

另请参见

持久性事件

method 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) ...

注意

此事件 **仅** 适用于 会话刷新操作,并且 **不** 适用于 ORM 启用的 INSERT、UPDATE 和 DELETE 语句 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

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

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

警告

映射器级刷新事件只允许执行 **非常有限的操作**,这些操作仅限于正在操作的行上的本地属性,并且允许在给定的 Connection 上发出任何 SQL。 **请仔细阅读** 映射器级刷新事件 中的说明,了解有关使用这些方法的指南;通常,SessionEvents.before_flush() 方法应优先用于一般刷新更改。

参数::
  • mapperMapper,它是此事件的目标。

  • connectionConnection,用于为该实例发出 INSERT 语句。这提供了一个句柄,指向特定于该实例的目标数据库上的当前事务。

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

返回值:

此事件不支持返回值。

另请参见

持久性事件

method 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() 事件来创建新的映射器,以记录对象的变化审核历史。

method 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) ...

注意

此事件 **仅** 适用于 会话刷新操作,并且 **不** 适用于 ORM 启用的 INSERT、UPDATE 和 DELETE 语句 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

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

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

若要检测对象的基于列的属性是否具有净变化,以及因此是否导致了 UPDATE 语句,请使用 object_session(instance).is_modified(instance, include_collections=False)

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

警告

映射器级刷新事件只允许执行 **非常有限的操作**,这些操作仅限于正在操作的行上的本地属性,并且允许在给定的 Connection 上发出任何 SQL。 **请仔细阅读** 映射器级刷新事件 中的说明,了解有关使用这些方法的指南;通常,SessionEvents.before_flush() 方法应优先用于一般刷新更改。

参数::
  • mapperMapper 是此事件的目标。

  • connectionConnection 用于为此实例发出 UPDATE 语句。这提供了对特定于此实例的目标数据库上的当前事务的处理。

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

返回值:

此事件不支持返回值。

另请参见

持久性事件

method 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():
    ...
method 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) ...

注意

此事件 **仅** 适用于 会话刷新操作,并且 **不** 适用于 ORM 启用的 INSERT、UPDATE 和 DELETE 语句 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

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

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

警告

映射器级刷新事件只允许执行 **非常有限的操作**,这些操作仅限于正在操作的行上的本地属性,并且允许在给定的 Connection 上发出任何 SQL。 **请仔细阅读** 映射器级刷新事件 中的说明,了解有关使用这些方法的指南;通常,SessionEvents.before_flush() 方法应优先用于一般刷新更改。

参数::
  • mapperMapper 是此事件的目标。

  • connectionConnection 用于为此实例发出 DELETE 语句。这提供了对特定于此实例的目标数据库上的当前事务的处理。

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

返回值:

此事件不支持返回值。

另请参见

持久性事件

method 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) ...

注意

此事件 **仅** 适用于 会话刷新操作,并且 **不** 适用于 ORM 启用的 INSERT、UPDATE 和 DELETE 语句 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

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

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

警告

映射器级刷新事件只允许执行 **非常有限的操作**,这些操作仅限于正在操作的行上的本地属性,并且允许在给定的 Connection 上发出任何 SQL。 **请仔细阅读** 映射器级刷新事件 中的说明,了解有关使用这些方法的指南;通常,SessionEvents.before_flush() 方法应优先用于一般刷新更改。

参数::
  • mapperMapper 是此事件的目标。

  • connectionConnection 用于为此实例发出 INSERT 语句。这提供了对特定于此实例的目标数据库上的当前事务的处理。

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

返回值:

此事件不支持返回值。

另请参见

持久性事件

method 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)应在当前配置运行中跳过。当一个或多个映射器被跳过时,he “new mappers” 标志将保持设置状态,这意味着当使用映射器时,configure_mappers() 函数将继续被调用,以继续尝试配置所有可用的映射器。

与其他配置级事件相比,MapperEvents.before_configured()MapperEvents.after_configured()MapperEvents.mapper_configured(),:meth;`.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
method 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) ...

注意

此事件 **仅** 适用于 会话刷新操作,并且 **不** 适用于 ORM 启用的 INSERT、UPDATE 和 DELETE 语句 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用 SessionEvents.do_orm_execute()

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

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

要检测对象上的基于列的属性是否有净变化,并且因此会生成 UPDATE 语句,请使用 object_session(instance).is_modified(instance, include_collections=False)

该事件通常会针对一批相同类的对象调用,然后在稍后的步骤中一次性发出它们的 UPDATE 语句。在极少数情况下,如果这不是可取的,则可以将 Mapper 配置为 batch=False,这会导致实例批次被分解成单个(并且性能更差)的事件->持久化->事件步骤。

警告

映射器级刷新事件只允许执行 **非常有限的操作**,这些操作仅限于正在操作的行上的本地属性,并且允许在给定的 Connection 上发出任何 SQL。 **请仔细阅读** 映射器级刷新事件 中的说明,了解有关使用这些方法的指南;通常,SessionEvents.before_flush() 方法应优先用于一般刷新更改。

参数::
  • mapper – 该事件的目标 Mapper

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

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

返回值:

此事件不支持返回值。

另请参见

持久性事件

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

对 _Dispatch 类进行反向引用。

与 _Dispatch._events 双向绑定

method 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_ – 映射类。

method 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() 事件被调用时,每个 mapper 在 configure_mappers() 函数遍历当前未配置的 mapper 列表时都会被调用。 configure_mappers() 通常会在第一次使用映射时自动调用,以及每次有新的 mapper 可用并且检测到新的 mapper 使用时都会被调用。

当事件被调用时,mapper 应该处于其最终状态,但不包括可能从其他 mapper 中调用的 backref;它们可能仍在配置操作中处于待处理状态。通过 relationship.back_populates 参数配置的双向关系完全可用,因为这种关系样式并不依赖于其他可能未配置的 mapper 来了解它们的存在。

对于一个保证所有 mapper 都已准备就绪的事件,包括仅在其他映射中定义的 backref,请使用 MapperEvents.after_configured() 事件;此事件仅在所有已知映射都已完全配置后才会调用。

MapperEvents.before_configured()MapperEvents.after_configured() 不同,MapperEvents.mapper_configured() 事件会针对每个 mapper/类单独调用,并且 mapper 会传递到事件本身。它还会针对特定 mapper 精确调用一次。因此,此事件对于需要在特定 mapper 基础上仅调用一次的配置步骤很有用,这些步骤不需要“backref”配置一定准备就绪。

参数::
  • mapperMapper 是此事件的目标。

  • class_ – 映射的类。

实例事件

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

对象名称 描述

InstanceEvents

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

class 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 类本身表示监听所有映射器。

实例事件与 mapper 事件密切相关,但它们更侧重于实例及其仪器,而不是其持久化系统。

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

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

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

  • restore_load_context=False

    适用于 InstanceEvents.load()InstanceEvents.refresh() 事件。在事件钩子完成时恢复对象的加载器上下文,以便正在进行的急切加载操作继续适当针对对象。如果未设置此标志,则从这些事件中的一个事件内将对象移至新的加载器上下文时会发出警告。

    版本 1.3.14 中的新增内容。

类签名

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

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

对 _Dispatch 类进行反向引用。

与 _Dispatch._events 双向绑定

method 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。

method 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() 事件被调用之前调用。

method 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__ 方法的关键字参数。可以就地修改此结构。

method 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__ 方法的关键字参数。

method 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) ...

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

警告

在结果行加载期间,当处理此实例收到的第一行时调用此事件。当使用急切加载和面向集合的属性时,加载后续集合项所需的额外行尚未加载/处理。这具有以下效果:集合不会完全加载,以及如果在该事件处理程序中执行会导致对该对象发出另一个数据库加载操作的操作,则该对象的“加载上下文”可能会发生更改并干扰仍在进行中的现有急切加载器。

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

  • 访问不在该行中的延迟属性,会触发“取消延迟”操作并刷新该对象

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

从 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

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

示例参数形式

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__ 返回的字典,包含要腌制的 state。

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() 方法对比,该方法在对象首次从查询中加载时调用。

注意

此事件在加载器进程内调用,在急切加载器可能完成之前,对象的 state 可能不完整。此外,对对象调用行级刷新操作将使对象进入新的加载器上下文,干扰现有的加载上下文。有关使用 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

在对象 state 持久化期间,包含列级默认值或 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() 相同,只是它在工作单元刷新流程内调用,并且仅包含具有列级默认值或 onupdate 处理程序的非主键列,包括 Python 可调用函数以及可能通过 RETURNING 子句获取的服务器端默认值和触发器。

注意

虽然 InstanceEvents.refresh_flush() 事件会针对 INSERT 的对象以及 UPDATE 的对象触发,但该事件主要针对 UPDATE 过程;它主要是一个内部制品,INSERT 操作也可以触发此事件,并且请注意,INSERT 行的主键列明确从该事件中省略。为了拦截新 INSERT 的对象的 state,SessionEvents.pending_to_persistent()MapperEvents.after_insert() 是更好的选择。

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

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

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

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

在与该对象关联的 state 解腌制后,接收一个对象实例。

示例参数形式

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__ 的字典,包含已腌制的 state 字典。

属性事件

属性事件在 ORM 映射对象的各个属性上发生事件时触发。这些事件构成了诸如 自定义验证函数 以及 backref 处理程序 的基础。

另请参见

更改属性行为

对象名称 描述

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”事件希望无条件地接收被替换的“old”值,即使这需要触发数据库加载。请注意,active_history 也可以通过 column_property()relationship() 直接设置。

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

  • 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) ...

追加事件在每个元素追加到集合时被调用。这适用于单项追加,也适用于“批量替换”操作。

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

  • value – 被追加的值。如果此监听器是用 retval=True 注册的,监听器函数必须返回此值,或者返回替换它的新值。

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

  • key

    当使用 AttributeEvents.include_key 参数设置为 True 建立事件时,这将是操作中使用的键,例如 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 – 如果对象不存在于集合中,则将被追加的值。

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

  • key

    当使用 AttributeEvents.include_key 参数设置为 True 建立事件时,这将是操作中使用的键,例如 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 来测试传入的发起者。

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

    当使用 AttributeEvents.include_key 参数设置为 True 来建立事件时,这将是操作中使用的键序列,通常仅用于字典更新。 如果没有使用 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

接收一个“集合释放”事件。

示例参数形式

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

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

Changed in version 1.2: 传递给 AttributeEvents.dispose_collection() 的集合现在将拥有释放之前的内容; 以前,集合将为空。

另请参见

AttributeEvents - 监听器选项的背景信息,例如传播到子类。

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

接收一个“集合初始化”事件。

示例参数形式

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) ...

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

例如,假设 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_adapter – 将调解对集合的内部访问的 CollectionAdapter

另请参见

AttributeEvents - 监听器选项的背景信息,例如传播到子类。

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

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

接收一个标量“初始化”事件。

示例参数形式

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() 事件处理程序也可以用来 **设置** 新返回的值,以便 Core 级别的默认生成函数有效地只触发一次,但在属性在非持久化对象上被访问的时刻。通常,当访问未初始化的属性时,不会对对象的 state 进行任何更改(更早的 SQLAlchemy 版本确实会更改对象的 state)。

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

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_CONSTANT。在 属性 Instrumentation 中给出的 active_column_defaults.py 示例说明了如何使用相同的方法来处理不断变化的默认值,例如时间戳生成器。在这个特定的例子中,没有必要这样做,因为 SOME_CONSTANT 无论如何都会是 INSERT 语句的一部分。

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

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

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

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 示例。

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

接收“修改”事件。

示例参数形式

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() 函数用于在没有设置任何特定值的情况下触发属性的修改事件时,会触发此事件。

1.2 版本新增。

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

  • initiator – 一个 Event 实例,表示事件的启动。

另请参见

AttributeEvents - 监听器选项的背景信息,例如传播到子类。

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

接收集合删除事件。

示例参数形式

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 – 要删除的值。

  • initiator – 一个 Event 实例,表示事件的启动。可以由 backref 处理程序修改其原始值,以控制链式事件传播。

  • key

    当事件使用 AttributeEvents.include_key 参数设置为 True 建立时,这将是操作中使用的键,例如 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

接收标量设置事件。

示例参数形式

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) ...

自版本 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 对象。这会影响烘焙查询扩展的直接使用以及它在关系的延迟加载器和急切加载器中的操作。为了重新建立正在缓存的查询,请使用 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 时,事件钩子将只调用一次,并且不会为特定查询的后续调用调用,而该查询正在被缓存。

版本 1.3.11 中新增: - 在 QueryEvents.before_compile() 事件中添加了“bake_ok”标记,并禁止使用“烘焙”扩展进行缓存,如果此标记未设置,则针对返回新的 Query 对象的事件处理程序进行缓存。

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

允许对 Query 对象进行修改,该对象位于 Query.delete() 中。

示例参数形式

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) ...

自版本 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
参数::
  • query – 一个 Query 实例;这也是给定“删除上下文”对象的 .query 属性。

  • delete_context – 一个“删除上下文”对象,它与 QueryEvents.after_bulk_delete.delete_context 中描述的相同类型。

版本 1.2.17 中的新增功能。

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

允许对 Query 对象进行修改,该对象位于 Query.update() 中。

示例参数形式

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) ...

自版本 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

如上所示,还可以修改“更新上下文”对象的 .values 字典。

参数::
  • query – 一个 Query 实例;这也是给定“更新上下文”对象的 .query 属性。

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

版本 1.2.17 中的新增功能。

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

对 _Dispatch 类进行反向引用。

与 _Dispatch._events 双向绑定

Instrumentation 事件

定义了 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

当属性被 instrumentation 时调用。

示例参数形式

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

在给定类被 instrumentation 后调用。

示例参数形式

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

在给定类取消 instrumentation 之前调用。

示例参数形式

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 双向绑定