SqlAlchemy 2.0 中文文档(二十六)(3)https://developer.aliyun.com/article/1560474
映射器事件
映射器事件钩子涵盖了与单个或多个Mapper
对象相关的事情,这些对象是将用户定义的类映射到Table
对象的中心配置对象。在Mapper
级别发生的事情包括:
- 每个对象的持久化操作 - 最常见的映射器钩子是工作单元钩子,如
MapperEvents.before_insert()
、MapperEvents.after_update()
等。这些事件与更粗粒度的会话级事件形成对比,如SessionEvents.before_flush()
,因为它们在每个对象的刷新过程中发生;虽然对象上的更细粒度活动更直接,但Session
功能的可用性有限。 - 映射器配置事件 - 另一类重要的映射器钩子是在类被映射时、映射器被最终化时以及当映射器集合被配置为相互引用时发生的事件。这些事件包括
MapperEvents.instrument_class()
、MapperEvents.before_mapper_configured()
和MapperEvents.mapper_configured()
在单个Mapper
级别,以及MapperEvents.before_configured()
和MapperEvents.after_configured()
在集合的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
类本身表示监听所有映射器。
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
- 取消链中所有后续事件处理程序。- 其他值 - 特定监听器指定的返回值。
成员
after_configured(), after_delete(), after_insert(), after_mapper_constructed(), after_update(), before_configured(), before_delete(), before_insert(), before_mapper_configured(), before_update(), dispatch, instrument_class(), mapper_configured()
类签名
类 sqlalchemy.orm.MapperEvents
(sqlalchemy.event.Events
)
method 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) ...
每次调用 configure_mappers()
函数完成其工作后,都会调用 MapperEvents.after_configured()
事件。通常在首次使用映射时自动调用 configure_mappers()
,以及每当新映射器可用并检测到新的映射器使用时。
将此事件与MapperEvents.mapper_configured()
事件进行对比,该事件在配置操作进行时基于每个映射器调用;与该事件不同,当调用此事件时,所有交叉配置(例如反向引用)也将对任何待定映射器可用。还与MapperEvents.before_configured()
进行对比,该事件在系列映射器配置之前调用。
此事件只能应用于Mapper
类,而不能应用于单个映射或映射类。它仅对所有映射作为一个整体调用:
from sqlalchemy.orm import Mapper @event.listens_for(Mapper, "after_configured") def go(): # ...
理论上,这个事件在每个应用程序中只调用一次,但实际上在任何新映射器受到configure_mappers()
调用时都会被调用。如果在已经使用现有映射后构造了新映射,则可能会再次调用此事件。要确保特定事件仅被调用一次且不再调用,可以应用once=True
参数(0.9.4 中新增):
from sqlalchemy.orm import mapper @event.listens_for(mapper, "after_configured", once=True) def go(): # ...
另请参阅
MapperEvents.before_mapper_configured()
MapperEvents.mapper_configured()
MapperEvents.before_configured()
method 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 语句后调用。
警告
Mapper 级别的刷新事件仅允许对仅限于操作的行的本地属性进行非常有限的操作,同时允许在给定的Connection
上发出任何 SQL。请完全阅读Mapper 级别的刷新事件中关于使用这些方法的指南;通常,应优先使用SessionEvents.before_flush()
方法进行一般的刷新更改。
参数:
mapper
– 此事件的目标Mapper
。connection
– 用于发出此实例的 DELETE 语句的Connection
。这为当前事务提供了一个处理该实例特定于目标数据库的句柄。target
– 正在删除的映射实例。如果事件配置为raw=True
,则这将是与实例关联的InstanceState
状态管理对象。
返回:
此事件不支持返回值。
另请参阅
持久性事件
method 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。 请务必充分阅读有关使用这些方法的指南的 Mapper 级别刷新事件的说明;一般情况下,应优先考虑SessionEvents.before_flush()
方法进行一般性刷新更改。
参数:
mapper
– 这个事件目标的Mapper
。connection
– 用于为此实例发出 INSERT 语句的Connection
。这提供了一个句柄到目标数据库上当前事务的处理,该事务特定于此实例。target
– 正在持久化的映射实例。如果事件配置为raw=True
,则这将是与实例关联的InstanceState
状态管理对象。
返回值:
不支持此事件的返回值。
另请参阅
持久化事件
method 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 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()
。
此事件用于修改更新后的实例上的仅在 Python 中的状态,以及在给定连接上发出附加 SQL 语句。
对于所有标记为“脏”的实例都会调用此方法,即使它们的基于列的属性没有任何净变化,并且没有进行 UPDATE 语句。当对象的任何基于列的属性被调用“设置属性”操作或其任何集合被修改时,对象被标记为脏。如果在更新时,没有基于列的属性有任何净变化,则不会发出 UPDATE 语句。这意味着被发送到MapperEvents.after_update()
的实例不能保证已发出 UPDATE 语句。
要检测对象上基于列的属性是否有净变化,从而导致 UPDATE 语句,请使用object_session(instance).is_modified(instance, include_collections=False)
。
在前一步骤一次性发出它们的 UPDATE 语句之后,往往为同一类对象的一批对象调用事件。在极其罕见的情况下,如果这不是可取的,Mapper
可以配置为batch=False
,这将导致实例批次被分解为单个(性能较差)事件->持久化->事件步骤。
警告
Mapper 级别的刷新事件仅允许对仅与正在操作的行本地属性进行非常有限的操作,并允许在给定的Connection
上发出任何 SQL。请完整阅读Mapper 级刷新事件的注释以获取有关使用这些方法的指南;一般而言,应首选SessionEvents.before_flush()
方法进行一般的刷新更改。
参数:
mapper
– 这个事件目标的Mapper
。connection
– 用于为此实例发出 UPDATE 语句的Connection
。这提供了一个句柄到当前事务的目标数据库,该事务特定于此实例。target
– 被持久化的映射实例。如果事件配置为raw=True
,则这将是与实例关联的InstanceState
状态管理对象。
返回:
此事件不支持返回值。
另请参阅
持久性事件
method 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) ...
每次调用configure_mappers()
函数时,都会调用MapperEvents.before_configured()
事件,在函数尚未执行任何工作之前。 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(): ...
另请参阅
MapperEvents.before_mapper_configured()
MapperEvents.mapper_configured()
MapperEvents.after_configured()
method 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-Enabled INSERT, UPDATE, 和 DELETE statements 中描述的 ORM DML 操作。要拦截 ORM DML 事件,请使用SessionEvents.do_orm_execute()
。
此事件用于在给定连接上发出额外的 SQL 语句,以及执行与删除事件相关的应用程序特定簿记。
该事件通常在后续步骤中一次性发出同一类对象的批量 DELETE 语句之前为其进行调用。
警告
仅允许在仅对操作的行本地属性上进行非常有限的操作,以及允许在给定的Connection
上发出任何 SQL 语句。请务必充分阅读Mapper-level Flush Events 中的注意事项,以获取使用这些方法的指南;通常,应优先使用SessionEvents.before_flush()
方法进行常规的刷新更改。
参数:
mapper
– 此事件的目标Mapper
。connection
– 用于为此实例发出 DELETE 语句的Connection
。这提供了一个句柄进入与此实例特定目标数据库上的当前事务。target
– 正在删除的映射实例。如果事件配置为raw=True
,则这将是与实例关联的InstanceState
状态管理对象。
返回:
此事件不支持返回值。
另请参阅
持久化事件
method 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 语句之前,通常为同一类对象的一批对象调用此事件。在极为罕见的情况下,如果这不是理想的情况,可以使用batch=False
配置Mapper
对象,这将导致实例批次被拆分为单个(性能较差)事件->持久化->事件步骤。
警告
Mapper 级别的刷新事件仅允许非常有限的操作,仅限于对正在操作的行本地属性的操作,以及允许在给定的Connection
上发出任何 SQL。请完全阅读Mapper 级别刷新事件中的注意事项,以获取有关使用这些方法的指南;通常,应优先使用SessionEvents.before_flush()
方法进行一般的刷新更改。
参数:
mapper
– 此事件的目标Mapper
。connection
– 用于为此实例发出 INSERT 语句的Connection
。这提供了一个在目标数据库上当前事务中使用的句柄,该事务特定于此实例。target
– 正在持久化的映射实例。如果事件配置为raw=True
,则这将改为与实例关联的InstanceState
状态管理对象。
返回:
此事件不支持返回值。
另请参阅
持久性事件
method before_mapper_configured(mapper: Mapper[_O], class_: Type[_O]) → None
在特定映射器配置之前调用。
示例参数形式:
from sqlalchemy import event @event.listens_for(SomeClass, 'before_mapper_configured') def receive_before_mapper_configured(mapper, class_): "listen for the 'before_mapper_configured' event" # ... (event handling logic) ...
此事件旨在允许在配置步骤中跳过特定映射器,方法是返回 interfaces.EXT_SKIP
符号,该符号表示向 configure_mappers()
调用指示此特定映射器(或如果使用 propagate=True
则是映射器层次结构)应在当前配置运行中被跳过。当跳过一个或多个映射器时,将保持“新映射器”标志设置,这意味着当使用映射器时,将继续调用 configure_mappers()
函数,以继续尝试配置所有可用的映射器。
与其他配置级事件 MapperEvents.before_configured()
、MapperEvents.after_configured()
和 MapperEvents.mapper_configured()
相比,当使用 retval=True
参数注册时,:meth;.MapperEvents.before_mapper_configured
事件在注册时提供了有意义的返回值。
版本 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
另请参阅
MapperEvents.before_configured()
MapperEvents.after_configured()
MapperEvents.mapper_configured()
method 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
,这将导致实例批次被拆分为单个(性能较差)事件->持久化->事件步骤。
警告
Mapper 级别的刷新事件仅允许非常有限的操作,仅限于操作的行本地属性,以及允许在给定的Connection
上发出任何 SQL。请完全阅读Mapper 级别刷新事件中的注意事项,以获取有关使用这些方法的指导;通常,应优先使用SessionEvents.before_flush()
方法进行一般的刷新更改。
参数:
mapper
– 此事件目标的Mapper
。connection
– 用于为此实例发出 UPDATE 语句的Connection
。这提供了一个句柄进入当前数据库的事务,特定于此实例。target
– 正在持久化的映射实例。如果事件配置为raw=True
,则这将是与实例关联的InstanceState
状态管理对象。
返回值:
此事件不支持返回值。
另请参见
持久性事件
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.MapperEventsDispatch object>
参考回到 _Dispatch 类。
双向反对 _Dispatch._events
method 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_
– 映射的类。
另请参见
MapperEvents.after_mapper_constructed()
method 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) ...
当 configure_mappers()
函数通过当前尚未配置的映射器列表进行时,对遇到的每个映射器调用 MapperEvents.mapper_configured()
事件。通常在首次使用映射时自动调用 configure_mappers()
,以及每次有新映射器可用并检测到新映射器使用时。
当调用事件时,映射器应处于最终状态,但不包括可能从其他映射器调用的反向引用;它们可能仍在配置操作中挂起。通过relationship.back_populates
参数配置的双向关系将完全可用,因为这种关系方式不依赖于其他可能尚未配置的映射器来知道它们的存在。
对于一个保证所有映射都准备就绪,包括仅在其他映射上定义的反向引用的事件,请使用MapperEvents.after_configured()
事件;此事件仅在所有已知映射完全配置后才调用。
与MapperEvents.before_configured()
或MapperEvents.after_configured()
不同,MapperEvents.mapper_configured()
事件为每个映射/类单独调用,并将映射器传递给事件本身。对于特定映射器,该事件仅调用一次。因此,该事件对于在特定映射器基础上仅调用一次的配置步骤非常有用,这些步骤不要求“反向引用”配置必须已准备就绪。
参数:
mapper
– 这个事件的目标是Mapper
。class_
– 映射的类。
另请参阅
MapperEvents.before_configured()
MapperEvents.after_configured()
MapperEvents.before_mapper_configured()
SqlAlchemy 2.0 中文文档(二十六)(5)https://developer.aliyun.com/article/1560481