Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

ORM事件

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

有关最常用的ORM事件的介绍,请参阅部分 使用事件跟踪查询、对象和会话更改 . 事件系统一般在 事件 . 有关连接和低级语句执行的非ORM事件如中所述。 核心事件 .

会话事件

最基本的事件钩子在ORM级别可用 Session 对象。这里截获的内容包括:

  • 持久性操作 -向数据库发送更改的ORM刷新过程可以使用在刷新的不同部分触发的事件进行扩展,以增加或修改发送到数据库的数据,或者允许在持久性发生时发生其他事情。阅读有关持久性事件的更多信息,请访问 持久性事件 .

  • 对象生命周期事件 -在会话中添加、持久化和删除对象时挂接。更多信息请访问 对象生命周期事件 .

  • 执行事件 -部分 2.0 style 执行模型、针对发出的ORM实体的所有SELECT语句,以及flush进程之外的批量更新和删除语句,都从 Session.execute() 方法使用 SessionEvents.do_orm_execute() 方法。有关此活动的更多信息,请访问 执行事件 .

请务必阅读 使用事件跟踪查询、对象和会话更改 关于这些事件的背景。

Object Name Description

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, instance)

在实例连接到会话后执行。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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, transaction, connection)

在连接上开始事务后执行

示例参数形式:

from sqlalchemy import event


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

    # ... (event handling logic) ...
参数
method sqlalchemy.orm.SessionEvents.after_bulk_delete(delete_context)

在调用了WHERE表达式的ORM DELETE之后执行。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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(SomeSessionOrFactory, 'after_bulk_delete')
def receive_after_bulk_delete(session, query, query_context, result):
    "listen for the 'after_bulk_delete' event"

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

0.9 版后已移除: 这个 after_bulk_delete 事件现在接受参数 delete_context . 对接受上面列出的“已弃用”参数签名的侦听器函数的支持将在将来的版本中删除。

这是由于 Query.delete() 方法。

参数

delete_context -- “删除上下文”对象,其中包含有关更新的详细信息,包括以下属性: * session - the Session involved * query - Query 调用此更新操作的对象。* result 这个 CursorResult 作为批量删除操作的结果返回。

在 1.4 版更改: update_上下文不再具有 QueryContext 与之关联的对象。

method sqlalchemy.orm.SessionEvents.after_bulk_update(update_context)

在针对WHERE表达式调用ORM更新后执行。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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(SomeSessionOrFactory, 'after_bulk_update')
def receive_after_bulk_update(session, query, query_context, result):
    "listen for the 'after_bulk_update' event"

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

0.9 版后已移除: 这个 after_bulk_update 事件现在接受参数 update_context . 对接受上面列出的“已弃用”参数签名的侦听器函数的支持将在将来的版本中删除。

这是由于 Query.update() 方法。

参数

update_context -- “更新上下文”对象,其中包含有关更新的详细信息,包括以下属性: * session - the Session involved * query - Query 调用此更新操作的对象。 * values The "values" dictionary that was passed to Query.update(). * result 这个 CursorResult 作为批量更新操作的结果返回。

在 1.4 版更改: update_上下文不再具有 QueryContext 与之关联的对象。

method sqlalchemy.orm.SessionEvents.after_commit(session)

在提交之后执行。

示例参数形式:

from sqlalchemy import event


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

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

注解

这个 SessionEvents.after_commit() 钩子是 not 每次冲洗,即 Session 可以在事务范围内多次向数据库发出SQL。要拦截这些事件,请使用 SessionEvents.before_flush()SessionEvents.after_flush()SessionEvents.after_flush_postexec() 事件。

注解

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

参数

session -- 目标 Session .

method sqlalchemy.orm.SessionEvents.after_flush(session, flush_context)

在刷新完成后但在调用提交之前执行。

示例参数形式:

from sqlalchemy import event


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

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

请注意,会话的状态仍然处于预刷新状态,即“新”、“脏”和“已删除”列表仍然显示预刷新状态以及实例属性的历史设置。

警告

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

参数
method sqlalchemy.orm.SessionEvents.after_flush_postexec(session, flush_context)

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

示例参数形式:

from sqlalchemy import event


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

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

这将在“新”、“脏”和“已删除”列表处于最终状态时进行。实际的commit()可能已经发生,也可能没有发生,这取决于刷新是否启动了自己的事务或是否参与了更大的事务。

参数
method sqlalchemy.orm.SessionEvents.after_rollback(session)

在实际DBAPI回滚发生后执行。

示例参数形式:

from sqlalchemy import event


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

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

请注意,此事件仅在 实际的 对数据库执行回滚-执行回滚 not 每次开火 Session.rollback() 如果基础DBAPI事务已回滚,则调用方法。在许多情况下, Session 在此事件期间不会处于“活动”状态,因为当前事务无效。获得一个 Session 在进行最外层回滚之后,使用 SessionEvents.after_soft_rollback() 事件,检查 Session.is_active 旗帜。

参数

session -- 目标 Session .

method sqlalchemy.orm.SessionEvents.after_soft_rollback(session, previous_transaction)

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

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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("select * from some_table")
参数
method sqlalchemy.orm.SessionEvents.after_transaction_create(session, transaction)

当新的 SessionTransaction 创建。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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.parent 属性是 None ::@event.listens_for(session,“after_transaction_create”)def after_transaction_create(session,transaction):if transaction.parent is none:使用顶级事务检测 SessionTransaction 是保存点,请使用 SessionTransaction.nested 属性::@event.listens_for(session,“after_transaction_create”)def after_transaction_create(session,transaction):if transaction.nested:使用保存点事务

method sqlalchemy.orm.SessionEvents.after_transaction_end(session, transaction)

SessionTransaction 末端。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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.parent 属性是 None ::@event.listens_for(session,“after_transaction_create”)def after_transaction_end(session,transaction):if transaction.parent is none:使用顶级事务检测 SessionTransaction 是保存点,请使用 SessionTransaction.nested 属性::@event.listens_for(session,“after_transaction_create”)def after_transaction_end(session,transaction):if transaction.nested:使用保存点事务

method sqlalchemy.orm.SessionEvents.before_attach(session, instance)

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

示例参数形式:

from sqlalchemy import event


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

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

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

method sqlalchemy.orm.SessionEvents.before_commit(session)

在调用提交之前执行。

示例参数形式:

from sqlalchemy import event


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

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

注解

这个 SessionEvents.before_commit() 钩子是 not 每次冲洗,即 Session 可以在事务范围内多次向数据库发出SQL。要拦截这些事件,请使用 SessionEvents.before_flush()SessionEvents.after_flush()SessionEvents.after_flush_postexec() 事件。

参数

session -- 目标 Session .

method sqlalchemy.orm.SessionEvents.before_flush(session, flush_context, instances)

在刷新进程启动之前执行。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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, instance)

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

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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() .

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.deleted_to_persistent(session, instance)

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

示例参数形式:

from sqlalchemy import event


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

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

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

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.detached_to_persistent(session, instance)

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

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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() 对象是 not 但在调用此事件时标记为已删除。要检测已删除的对象,请检查 deleted 标志发送到 SessionEvents.persistent_to_detached() 在冲洗进行后发生事件,或检查 Session.deletedSessionEvents.before_flush() 事件,如果在刷新之前需要截取已删除的对象。

参数
  • session -- 目标 Session

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

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.do_orm_execute(orm_execute_state)

根据 Session .

示例参数形式:

from sqlalchemy import event


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

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

对于从中调用的所有顶级SQL语句调用此事件 Session.execute() 方法。从SQLAlchemy 1.4开始,所有代表 Session 将流经此方法,因此此事件钩子提供一个点,在调用所有类型的ORM查询之前,可以在该点截获这些查询,并用不同的进程替换它们的执行。

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

这个钩子打算用 Query._execute_and_instances 方法,该方法可以在SQLAlchemy 1.4之前子类化。

参数

orm_execute_state -- 一个实例 ORMExecuteState 它包含有关当前执行的所有信息,以及用于派生其他常用信息的助手函数。有关详细信息,请参见该对象。

参见

执行事件 - top level documentation on how to use SessionEvents.do_orm_execute()

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

ORM查询事件 - includes examples of using SessionEvents.do_orm_execute()

狗堆缓存 -一个如何将Dogpile缓存与ORM集成的示例 Session 利用 SessionEvents.do_orm_execute() 事件挂钩。

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

1.4 新版功能.

method sqlalchemy.orm.SessionEvents.loaded_as_persistent(session, instance)

截取特定对象的“作为永久加载”转换。

示例参数形式:

from sqlalchemy import event


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

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

此事件在ORM加载过程中被调用,并且被调用与 InstanceEvents.load() 事件。然而,这里的事件与 Session 类或实例,而不是映射器或类层次结构,并与其他会话生命周期事件顺利集成。当调用此事件时,该对象保证存在于会话的标识映射中。

注解

此事件在加载器进程中调用,在预先加载程序完成之前,并且对象的状态可能未完成。另外,对对象调用行级刷新操作会将对象放入新的加载程序上下文中,从而干扰现有的加载上下文。请参见 InstanceEvents.load() 关于利用 SessionEvents.restore_load_context 参数,其工作方式与 InstanceEvents.restore_load_context ,以解决此问题。

参数
  • session -- 目标 Session

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

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.pending_to_persistent(session, instance)

截获特定对象的“挂起到永久”转换。

示例参数形式:

from sqlalchemy import event


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

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

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

参数
  • session -- 目标 Session

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

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.pending_to_transient(session, instance)

拦截特定对象的“挂起到暂时”转换。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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映射实例。

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.persistent_to_deleted(session, instance)

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

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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() 因此,在刷新结束时调用事件。

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.persistent_to_detached(session, instance)

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

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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,则表示此对象已移动到分离状态,因为它已标记为已删除和刷新。

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.persistent_to_transient(session, instance)

截取特定对象的“持续到暂时”转换。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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映射实例。

1.1 新版功能.

method sqlalchemy.orm.SessionEvents.transient_to_pending(session, instance)

截取特定对象的“暂时到挂起”转换。

示例参数形式:

from sqlalchemy import event


@event.listens_for(SomeSessionOrFactory, '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映射实例。

1.1 新版功能.

映射事件

映射器事件钩子包含与单个或多个相关的事件 Mapper 对象,它是将用户定义的类映射到 Table 对象。发生在 Mapper 级别包括:

Object Name Description

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 类本身和 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 - continue event processing normally. * sqlalchemy.orm.interfaces.EXT_STOP -取消链中的所有后续事件处理程序。*其他值-特定侦听器指定的返回值。

类签名

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

method sqlalchemy.orm.MapperEvents.after_configured()

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

示例参数形式:

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() ,在配置映射器系列之前调用。

这个事件可以 only 应用于 Mapper 类或 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, connection, target)

在发出与该实例对应的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) ...

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

在上一步中,当同一类的一批对象的DELETE语句同时发出后,通常会调用该事件。

警告

映射器级别刷新事件仅允许 非常有限的操作 ,并允许在给定的 Connection . 请详细阅读 笔记在 映射器级别事件 关于使用这些方法的指南;一般来说, SessionEvents.before_flush() 对于一般的刷新更改,应首选方法。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

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

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

返回

此事件不支持返回值。

method sqlalchemy.orm.MapperEvents.after_insert(mapper, connection, target)

在对应于该实例发出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) ...

此事件用于在发生插入后在实例上以仅Python状态进行修改,以及在给定连接上发出其他SQL语句。

在上一步中,一次发出insert语句后,通常会为同一类的一批对象调用该事件。在极为罕见的情况下,这是不可取的, mapper() 可配置为 batch=False ,这将导致成批的实例被分解为单独的(性能更差的)事件->持久化->事件步骤。

警告

映射器级别刷新事件仅允许 非常有限的操作 ,并允许在给定的 Connection . 请详细阅读 笔记在 映射器级别事件 关于使用这些方法的指南;一般来说, SessionEvents.before_flush() 对于一般的刷新更改,应首选方法。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

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

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

返回

此事件不支持返回值。

method sqlalchemy.orm.MapperEvents.after_update(mapper, connection, target)

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

示例参数形式:

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

此事件用于在更新发生后在实例上以仅Python状态进行修改,以及在给定连接上发出其他SQL语句。

对标记为“脏”的所有实例调用此方法, even those which have no net changes to their column-based attributes ,并且没有执行任何更新语句。当对象的任何基于列的属性调用了“set attribute”操作或修改了其任何集合时,该对象被标记为脏对象。如果在更新时,没有基于列的属性有任何净更改,则不会发出更新语句。这意味着一个实例被发送到 MapperEvents.after_update()not 已发布更新声明的保证。

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

在上一步中,一批同一类的对象的update语句一次发出之后,通常会调用该事件。在极为罕见的情况下,这是不可取的, mapper() 可配置为 batch=False ,这将导致成批的实例被分解为单独的(性能更差的)事件->持久化->事件步骤。

警告

映射器级别刷新事件仅允许 非常有限的操作 ,并允许在给定的 Connection . 请详细阅读 笔记在 映射器级别事件 关于使用这些方法的指南;一般来说, SessionEvents.before_flush() 对于一般的刷新更改,应首选方法。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

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

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

返回

此事件不支持返回值。

method sqlalchemy.orm.MapperEvents.before_configured()

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

示例参数形式:

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() 通常在首次使用映射时自动调用,以及每次新映射器可用并检测到新映射器使用时自动调用。

这个事件可以 only 应用于 Mapper 类或 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():
    # ...

0.9.3 新版功能.

method sqlalchemy.orm.MapperEvents.before_delete(mapper, connection, target)

在对应于该实例发出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) ...

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

在稍后的步骤中,在同时发出delete语句之前,通常会为同一类的一批对象调用该事件。

警告

映射器级别刷新事件仅允许 非常有限的操作 ,并允许在给定的 Connection . 请详细阅读 笔记在 映射器级别事件 关于使用这些方法的指南;一般来说, SessionEvents.before_flush() 对于一般的刷新更改,应首选方法。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

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

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

返回

此事件不支持返回值。

method sqlalchemy.orm.MapperEvents.before_insert(mapper, connection, target)

在对应于该实例发出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) ...

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

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

警告

映射器级别刷新事件仅允许 非常有限的操作 ,并允许在给定的 Connection . 请详细阅读 笔记在 映射器级别事件 关于使用这些方法的指南;一般来说, SessionEvents.before_flush() 对于一般的刷新更改,应首选方法。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

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

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

返回

此事件不支持返回值。

method sqlalchemy.orm.MapperEvents.before_mapper_configured(mapper, class_)

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

示例参数形式:

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() ,则: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, connection, target)

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

示例参数形式:

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

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

对标记为“脏”的所有实例调用此方法, even those which have no net changes to their column-based attributes . 当对象的任何基于列的属性调用了“set attribute”操作或修改了其任何集合时,该对象被标记为脏对象。如果在更新时,没有基于列的属性有任何净更改,则不会发出更新语句。这意味着一个实例被发送到 MapperEvents.before_update()not 保证将发出更新语句,尽管您可以通过修改属性来影响此处的结果,从而使值确实存在净变化。

若要检测对象上基于列的属性是否有净更改,从而生成更新语句,请使用 object_session(instance).is_modified(instance, include_collections=False) .

在稍后的步骤中,在一次发出更新语句之前,通常会为同一类的一批对象调用事件。在极为罕见的情况下,这是不可取的, mapper() 可配置为 batch=False ,这将导致成批的实例被分解为单独的(性能更差的)事件->持久化->事件步骤。

警告

映射器级别刷新事件仅允许 非常有限的操作 ,并允许在给定的 Connection . 请详细阅读 笔记在 映射器级别事件 关于使用这些方法的指南;一般来说, SessionEvents.before_flush() 对于一般的刷新更改,应首选方法。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

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

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

返回

此事件不支持返回值。

method sqlalchemy.orm.MapperEvents.instrument_class(mapper, class_)

在将检测应用于映射类之前,在第一次构造映射器时接收类。

示例参数形式:

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 整体类,或作为将要映射的类的基础的任何未映射类(使用 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, class_)

当特定映射器在 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 参数 will 完全可用,因为这种类型的关系不依赖于其他可能未配置的映射器来知道它们的存在。

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

这个 MapperEvents.mapper_configured() 事件,不像 MapperEvents.before_configured()MapperEvents.after_configured() 分别为每个映射器/类调用,并将映射器传递给事件本身。对于一个特定的映射器,它也恰好被调用一次。因此,对于配置步骤来说,该事件非常有用,因为在特定的映射器基础上只调用一次,而不需要“backref”配置就已经准备好了。

参数
  • mapper -- 这个 Mapper 这是这次活动的目标。

  • class_ -- 映射的类。

实例事件

实例事件集中在ORM映射实例的构造上,包括它们被实例化为 transient 对象,当它们从数据库加载并成为 persistent 对象,以及对对象执行数据库刷新或过期操作时。

Object Name Description

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)

method sqlalchemy.orm.InstanceEvents.expire(target, attrs)

在对象实例的属性或某个子集过期后接收该实例。

示例参数形式:

from sqlalchemy import event


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

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

“keys”是属性名的列表。如果没有,则整个状态将过期。

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

  • attrs -- 过期的属性名序列,如果所有属性都过期,则为无。

method sqlalchemy.orm.InstanceEvents.first_init(manager, cls)

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

示例参数形式:

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, args, kwargs)

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

示例参数形式:

from sqlalchemy import event


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

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

此方法仅在对象的userland构造期间与对象的构造函数一起调用,例如 __init__ 方法。当从数据库加载对象时,不会调用它;请参见 InstanceEvents.load() 事件以拦截数据库加载。

事件在实际 __init__ 调用对象的构造函数。这个 kwargs 可以在适当的位置修改字典,以影响传递到的内容 __init__ .

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

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

  • kwargs -- 传递给的关键字参数 __init__ 方法。这种结构 can 就地更改。

method sqlalchemy.orm.InstanceEvents.init_failure(target, args, kwargs)

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

示例参数形式:

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

此方法仅在对象的userland构造期间与对象的构造函数一起调用,例如 __init__ 方法。当从数据库加载对象时,不会调用它。

事件在引发异常后被调用 __init__ 方法被捕获。调用事件后,原始异常将被向外重新引发,因此对象的构造仍会引发异常。引发的实际异常和堆栈跟踪应出现在 sys.exc_info() .

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

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

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

method sqlalchemy.orm.InstanceEvents.load(target, context)

通过以下方式创建对象实例后接收该实例 __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() 事件也可以用类方法decorator格式调用 reconstructor() .

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

  • context -- 这个 QueryContext 对应于电流 Query 正在进行中。这个论点可能是 None 如果负载不符合 Query ,例如在 Session.merge() .

method sqlalchemy.orm.InstanceEvents.pickle(target, state_dict)

在对象实例的关联状态被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__ ,包含要腌制的状态。

method sqlalchemy.orm.InstanceEvents.refresh(target, context, attrs)

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

示例参数形式:

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

注解

此事件在加载器进程中调用,在预先加载程序完成之前,并且对象的状态可能未完成。另外,对对象调用行级刷新操作会将对象放入新的加载程序上下文中,从而干扰现有的加载上下文。请参见 InstanceEvents.load() 关于利用 InstanceEvents.restore_load_context 参数,以解决此方案。

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

  • context -- 这个 QueryContext 对应于电流 Query 正在进行中。

  • attrs -- 填充的属性名序列,如果填充了所有列映射的非延迟属性,则为无。

method sqlalchemy.orm.InstanceEvents.refresh_flush(target, flush_context, attrs)

在对象状态持久化期间,在刷新一个或多个包含列级默认或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() 事件对于已插入的对象和已更新的对象都会触发,该事件主要针对更新过程;它主要是一个内部构件,插入操作也可以触发此事件,请注意 插入行的主键列显式省略 从这次事件中。为了截获对象的新插入状态 SessionEvents.pending_to_persistent()MapperEvents.after_insert() 是更好的选择。

1.0.5 新版功能.

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

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

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

method sqlalchemy.orm.InstanceEvents.unpickle(target, state_dict)

在取消勾选对象实例的关联状态后接收该实例。

示例参数形式:

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

属性事件

属性事件在ORM映射对象的各个属性上发生时触发。这些事件构成了 custom validation functions 以及 backref handlers .

Object Name Description

AttributeEvents

定义对象属性的事件。

class sqlalchemy.orm.AttributeEvents

定义对象属性的事件。

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

例如。::

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

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,则将不仅为给定的class属性建立listener函数,而且为该类的所有当前子类以及该类的所有未来子类上同名的属性建立listener函数,使用一个额外的侦听器来侦听插入事件。

  • raw=False -- 如果为true,则事件的“target”参数将是 InstanceState 管理对象,而不是映射实例本身。

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

类签名

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

method sqlalchemy.orm.AttributeEvents.append(target, value, initiator)

接收集合追加事件。

示例参数形式:

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 ,Listener函数必须返回该值,或替换该值的新值。

  • initiator -- 的实例 Event 表示事件的开始。可以由backref处理程序从其原始值进行修改,以控制链接的事件传播,并检查有关事件源的信息。

返回

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

参见

AttributeEvents -侦听器选项的背景,如到子类的传播。

AttributeEvents.bulk_replace()

method sqlalchemy.orm.AttributeEvents.append_wo_mutation(target, value, initiator)

接收集合未实际变异的集合追加事件。

示例参数形式:

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 当集合已经通过backref事件发生变异时。

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

  • value -- 如果集合中尚不存在该对象,将追加的值。

  • initiator -- 的实例 Event 表示事件的开始。可以由backref处理程序从其原始值进行修改,以控制链接的事件传播,并检查有关事件源的信息。

返回

没有为此事件定义返回值。

1.4.15 新版功能.

method sqlalchemy.orm.AttributeEvents.bulk_replace(target, values, initiator)

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

示例参数形式:

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对象之前,可以就地修改这些值。这是一个“早期钩子”,在大容量替换例程尝试协调集合中已经存在的对象以及由net replace操作删除的对象之前运行。

这种方法通常与 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 -- 正在设置的值的序列(例如列表)。处理程序可以就地修改此列表。

  • initiator -- 的实例 Event 表示事件的开始。

参见

AttributeEvents -侦听器选项的背景,如到子类的传播。

method sqlalchemy.orm.AttributeEvents.dispose_collection(target, collection, collection_adapter)

接收“Collection 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() 在释放之前将保持其内容完整;以前,集合将为空。

参见

AttributeEvents -侦听器选项的背景,如到子类的传播。

method sqlalchemy.orm.AttributeEvents.init_collection(target, collection, collection_adapter)

接收“collection 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) ...

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

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

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

以及在更换操作期间:

u1.addresses = [a2, a3]  #  <- new collection
参数

参见

AttributeEvents -侦听器选项的背景,如到子类的传播。

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

method sqlalchemy.orm.AttributeEvents.init_scalar(target, value, dict_)

接收标量“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) ...

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

x = my_object.some_attribute

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

因为默认生成器 Column 可能还会产生一个变化的值,例如时间戳, AttributeEvents.init_scalar() 事件处理程序也可用于 set 新返回的值,以便核心级别的默认生成函数只有效地触发一次,但此时对非持久化对象访问属性。通常,当访问未初始化的属性时,不会对对象的状态进行任何更改(更旧的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 . 上述代码包括以下功能:

  • 通过设置值 SOME_CONSTANT 在给定的 dict_ ,我们指示将此值持久化到数据库。这将取代 SOME_CONSTANT 在默认生成器中 Column . 这个 active_column_defaults.py 示例如下: 属性检测 说明对更改的默认值(例如时间戳生成器)使用相同的方法。在这个特定的例子中,没有严格必要这样做,因为 SOME_CONSTANT 在这两种情况下都是insert语句的一部分。

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

  • 这个 propagate=True 如果映射类包含继承子类,则标志很重要,这也将使用此事件侦听器。如果没有此标志,继承子类将不会使用事件处理程序。

在上面的示例中,属性集事件 AttributeEvents.set() 以及由提供的相关验证功能 validatesnot 当我们将值应用于给定的 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 下一个侦听器的参数。

1.1 新版功能.

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

  • value -- 在调用此事件侦听器之前要返回的值。此值以值开头 None 但是,如果存在多个侦听器,则返回上一个事件处理程序函数的值。

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

参见

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

AttributeEvents -侦听器选项的背景,如到子类的传播。

属性检测 -见 active_column_defaults.py 例子。

method sqlalchemy.orm.AttributeEvents.modified(target, initiator)

接收“已修改”事件。

示例参数形式:

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 -侦听器选项的背景,如到子类的传播。

method sqlalchemy.orm.AttributeEvents.remove(target, value, initiator)

接收集合移除事件。

示例参数形式:

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处理程序从其原始值进行修改,以控制链接的事件传播。…版本更改::0.9.0 initiator 参数现在作为 Event 对象,并且可以由backref链接事件链中的backref处理程序修改。

返回

没有为此事件定义返回值。

参见

AttributeEvents -侦听器选项的背景,如到子类的传播。

method sqlalchemy.orm.AttributeEvents.set(target, value, oldvalue, initiator)

接收标量集事件。

示例参数形式:

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 ,Listener函数必须返回该值,或替换该值的新值。

  • oldvalue -- 正在替换上一个值。这也可能是符号 NEVER_SETNO_VALUE . 如果侦听器注册在 active_history=True ,如果现有值当前已卸载或过期,则将从数据库加载该属性的上一个值。

  • initiator -- 的实例 Event 表示事件的开始。可以由backref处理程序从其原始值进行修改,以控制链接的事件传播。…版本更改::0.9.0 initiator 参数现在作为 Event 对象,并且可以由backref链接事件链中的backref处理程序修改。

返回

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

参见

AttributeEvents -侦听器选项的背景,如到子类的传播。

查询事件

Object Name Description

QueryEvents

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

class sqlalchemy.orm.QueryEvents

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

这个 QueryEvents 钩子现在被 SessionEvents.do_orm_execute() 事件挂钩。

类签名

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

method sqlalchemy.orm.QueryEvents.before_compile(query)

接收 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 对象。这既会影响baked查询扩展的直接使用,也会影响其在lazy loader和eager loader中的操作。为了重新建立正在缓存的查询,应用添加 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() 对于返回新的 Query 对象(如果未设置此标志)。

method sqlalchemy.orm.QueryEvents.before_compile_delete(query, delete_context)

允许修改 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, update_context)

允许修改 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.utcnow()
    return query

这个 .values “更新上下文”对象的字典也可以就地修改,如上图所示。

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

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

1.2.17 新版功能.

检测事件

定义SQLAlchemy的类检测系统。

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

py处理状态跟踪的最终用户类注册。它与state.py和attributes.py紧密交互,分别建立每个实例和每个类的属性检测。

可以使用 sqlalchemy.ext.instrumentation 模块,它提供了构建和指定备用仪表表单的方法。

Object Name Description

InstrumentationEvents

与类检测事件相关的事件。

class sqlalchemy.orm.InstrumentationEvents

与类检测事件相关的事件。

这里的侦听器支持针对任何新的样式类(即任何属于“type”子类的对象)建立。然后,针对该类的事件将触发事件。如果将“propagate=true”标志传递给event.listen(),那么该类的子类也将触发该事件。

Python type builtin也被接受为一个目标,当使用时,它具有为所有类发出事件的效果。

注意这里的“传播”标志默认为 True ,与默认为的其他类级事件不同 False . 这意味着当监听器建立在超类上时,新的子类也将成为这些事件的主题。

类签名

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

method sqlalchemy.orm.InstrumentationEvents.attribute_instrument(cls, key, inst)

在检测属性时调用。

示例参数形式:

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)

在检测给定类之后调用。

示例参数形式:

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)

在给定类未被构造之前调用。

示例参数形式:

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

Previous: 事件和内部 Next: ORM内构件