SqlAlchemy 2.0 中文文档(二十六)(5)

简介: SqlAlchemy 2.0 中文文档(二十六)

SqlAlchemy 2.0 中文文档(二十六)(4)https://developer.aliyun.com/article/1560477


实例事件

实例事件专注于 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类本身指示侦听所有映射器。

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

使用InstanceEvents时,listen()函数提供了几个修饰符。

参数:

  • propagate=False – 当为 True 时,事件监听器应该应用于所有继承类,以及作为此监听器目标的类。
  • raw=False – 当为 True 时,适用的事件监听器函数传递给“target”参数将是实例的InstanceState管理对象,而不是映射实例本身。
  • restore_load_context=False
    适用于InstanceEvents.load()InstanceEvents.refresh()事件。在事件钩子完成后恢复对象的加载器上下文,以便持续的急加载操作继续适当地针对对象。如果在这些事件之一内部将对象移动到新的加载器上下文中并且未设置此标志,则会发出警告。
    版本 1.3.14 中的新内容。

成员

dispatch, expire(), first_init(), init(), init_failure(), load(), pickle(), refresh(), refresh_flush(), unpickle()

类签名

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

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

回溯到 _Dispatch 类。

双向对 _Dispatch._events

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

另请参阅

InstanceEvents.init_failure()

InstanceEvents.load()

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

另请参阅

InstanceEvents.init()

InstanceEvents.load()

method 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

另请参阅

维护跨加载的非映射状态

InstanceEvents.init()

InstanceEvents.refresh()

SessionEvents.loaded_as_persistent()

method pickle(target: _O, state_dict: _InstanceDict) → None

在其关联状态被 pickled 时接收对象实例。

示例参数形式:

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__返回的字典,包含要被 pickled 的状态。
method 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()方法形成对比,当对象首次从查询中加载时会调用该方法。

注意

在加载器进程中在急切加载器可能已完成之前调用此事件,并且对象的状态可能不完整。此外,在对象上调用行级刷新操作将使对象进入新的加载器上下文,干扰现有的加载上下文。有关如何利用InstanceEvents.restore_load_context参数解决此场景的背景,请参阅有关InstanceEvents.load()的注释。

参数:

  • target – 映射实例。如果事件配置为raw=True,则这将是与实例关联的InstanceState状态管理对象。
  • context – 与当前进行中的Query对应的QueryContext
  • attrs – 已填充的属性名称序列,如果所有列映射的非延迟属性都已填充,则为 None。

另请参阅

在加载过程中保持非映射状态

InstanceEvents.load()

method refresh_flush(target: _O, flush_context: UOWTransaction, attrs: Iterable[str] | None) → None

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

示例参数形式:

from sqlalchemy import event
@event.listens_for(SomeClass, 'refresh_flush')
def receive_refresh_flush(target, flush_context, attrs):
    "listen for the 'refresh_flush' event"
    # ... (event handling logic) ...

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

注意

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

参数:

  • target – 映射实例。如果事件配置为raw=True,那么这将是与实例关联的InstanceState状态管理对象。
  • flush_context – 处理刷新细节的内部UOWTransaction对象。
  • attrs – 被填充的属性名称序列。

另请参阅

在加载过程中保持非映射状态

获取服务器生成的默认值

列的 INSERT/UPDATE 默认值

method unpickle(target: _O, state_dict: _InstanceDict) → None

在关联状态被反 pickle 后,收到一个对象实例。

示例参数形式:

from sqlalchemy import event
@event.listens_for(SomeClass, 'unpickle')
def receive_unpickle(target, state_dict):
    "listen for the 'unpickle' event"
    # ... (event handling logic) ...

参数:

  • target – 映射实例。如果事件配置为raw=True,那么这将是与实例关联的InstanceState状态管理对象。
  • state_dict – 发送给__setstate__的字典,包含被 pickle 的状态字典。

属性事件

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

另请参阅

更改属性行为

对象名称 描述
AttributeEvents 为对象属性定义事件。
class sqlalchemy.orm.AttributeEvents

为对象属性定义事件。

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

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

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

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

def validate_phone(target, value, oldvalue, initiator):
    "Strip non-numeric characters from a phone number"
    return re.sub(r'\D', '', value)
# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)

类似上述的验证函数也可以引发异常,如ValueError以停止操作。

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

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

listen()listens_for() 函数可用的所有修饰符如下。

参数:

  • active_history=False – 当为 True 时,表示“set”事件希望无条件接收被替换的“旧”值,即使这需要触发数据库加载。请注意,active_history也可以通过column_property()relationship()直接设置。
  • propagate=False – 当为 True 时,监听器函数将不仅为给定的类属性建立,还将为该类的所有当前子类以及该类的所有未来子类上具有相同名称的属性建立一个额外的监听器,该监听器监听仪器事件。
  • raw=False – 当为 True 时,事件的“target”参数将是InstanceState管理对象,而不是映射实例本身。
  • retval=False – 当为 True 时,用户定义的事件监听必须从函数返回“value”参数。这使得监听函数有机会改变最终用于“set”或“append”事件的值。

成员

append(), append_wo_mutation(), bulk_replace(), dispatch,  dispose_collection(), init_collection(), init_scalar(), modified(),  remove(), set()

类签名

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

method 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实例。可能会被 backref 处理程序修改其原始值,以控制链式事件传播,同时也可以被检查以获取有关事件源的信息。
  • key
    当使用AttributeEvents.include_key参数设置为 True 来建立事件时,这将是操作中使用的键,例如collection[some_key_or_index] = value。如果未使用AttributeEvents.include_key设置事件,则根本不会传递该参数;这是为了允许与不包括key参数的现���事件处理程序向后兼容。
    2.0 版中的新内容。

返回值:

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

另请参阅

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

AttributeEvents.bulk_replace()

method 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 bulk_replace(target: _O, values: Iterable[_T], initiator: Event, *, keys: Iterable[EventConstants] | None = None) → None

接收一个集合‘批量替换’事件。

示例参数形式:

from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'bulk_replace')
def receive_bulk_replace(target, values, initiator):
    "listen for the 'bulk_replace' event"
    # ... (event handling logic) ...

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

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

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

版本 1.2 中的新功能。

参数:

  • target – 接收事件的对象实例。如果监听器以raw=True注册,这将是InstanceState对象。
  • value – 被设置的值的序列(例如列表)。处理程序可以直接修改此列表。
  • initiator – 代表事件启动的Event实例。
  • keys
    当使用AttributeEvents.include_key参数设置为 True 来建立事件时,这将是操作中使用的键的序列,通常仅用于字典更新。如果未使用AttributeEvents.include_key设置事件,参数根本不会传递给事件;这是为了允许与不包括key参数的现有事件处理程序保持向后兼容。
    版本 2.0 中的新功能。

另请参见

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

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

参考回到 _Dispatch 类。

双向对 _Dispatch._events

method 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

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

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

另请参见

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

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

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

例如,给定User.addresses是基于关系的集合,此处触发事件:

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

并且在替换操作期间也是如此:

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

参数:

  • target – 接收事件的对象实例。如果监听器注册为raw=True,则这将是InstanceState对象。
  • collection – 新的集合。这将始终从relationship.collection_class中指定的内容生成,并且始终为空。
  • collection_adapter – 将调解对集合的内部访问的CollectionAdapter

另请参阅

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

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

method init_scalar(target: _O, value: _T, dict_: Dict[Any, Any]) → None

接收一个标量“init”事件。

示例参数形式:

from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'init_scalar')
def receive_init_scalar(target, value, dict_):
    "listen for the 'init_scalar' event"
    # ... (event handling logic) ...

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

x = my_object.some_attribute

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

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

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

SOME_CONSTANT = 3.1415926
class MyClass(Base):
    # ...
    some_attribute = Column(Numeric, default=SOME_CONSTANT)
@event.listens_for(
    MyClass.some_attribute, "init_scalar",
    retval=True, propagate=True)
def _init_some_attribute(target, dict_, value):
    dict_['some_attribute'] = SOME_CONSTANT
    return SOME_CONSTANT

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

  • 通过在给定的dict_中设置值SOME_CONSTANT,我们指示该值将被持久化到数据库中。这将取代在Column的默认生成器中使用SOME_CONSTANT。在属性仪器化中给出的active_column_defaults.py示例说明了使用相同方法进行更改默认值的方法,例如时间戳生成器。在这个特定的例子中,这样做并不是严格必要的,因为SOME_CONSTANT无论如何都会成为 INSERT 语句的一部分。
  • 通过建立retval=True标志,我们从函数返回的值将由属性获取器返回。没有此标志,事件被视为被动观察者,我们函数的返回值将被忽略。
  • 如果映射类包括继承的子类,则propagate=True标志是重要的,这些子类也会使用此事件侦听器。没有此标志,继承的子类将不使用我们的事件处理程序。

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

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

当设置了多个侦听器时,值的生成会从一个侦听器“链式”传递到下一个侦听器,通过将由前一个指定了retval=True的侦听器返回的值作为下一个侦听器的value参数传递。

参数:

  • target – 接收事件的对象实例。如果侦听器使用raw=True注册,这将是InstanceState对象。
  • value – 在调用此事件侦听器之前要返回的值。此值最初为值None,但如果存在多个侦听器,则将是前一个事件处理程序函数的返回值。
  • dict_ – 此映射对象的属性字典。这通常是对象的__dict__,但在所有情况下都表示属性系统用于访问此属性的实际值的目标。将值放入此字典中的效果是该值将在工作单元生成的 INSERT 语句中使用。

另请参见

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

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

属性仪表化 - 查看 active_column_defaults.py 示例。

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

method 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 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,则如果现有值当前未加载或过期,则将从数据库加载属性的先前值。
  • initiator – 代表事件启动的Event实例。可能会被 backref 处理程序修改其原始值,以控制链式事件传播。

返回值:

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

另请参阅

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

查询事件

对象名称 描述
QueryEvents 在构建Query对象时表示事件。
class sqlalchemy.orm.QueryEvents

在构建Query对象时表示事件。

传统特性

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

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

成员

before_compile(), before_compile_delete(), before_compile_update(), dispatch

类签名

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

method before_compile(query: Query) → None

在将其组成为核心Select对象之前接收Query对象。

示例参数形式:

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()事件将禁止“baked”查询缓存查询,如果事件钩子返回一个新的Query对象。这影响到对烘焙查询扩展的直接使用以及它在延迟加载器和关系的贪婪加载器中的操作。为了重新建立缓存查询,请应用添加了bake_ok标志的事件:

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

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

从版本 1.3.11 开始:- 在QueryEvents.before_compile()事件中添加了“bake_ok”标志,并且如果未设置此标志,则不允许通过“baked”扩展缓存返回新的Query对象的事件处理程序发生。

另请参阅

QueryEvents.before_compile_update()

QueryEvents.before_compile_delete()

使用 before_compile 事件

method before_compile_delete(query: Query, delete_context: BulkDelete) → None

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

示例参数形式:

from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile_delete')
def receive_before_compile_delete(query, delete_context):
    "listen for the 'before_compile_delete' event"
    # ... (event handling logic) ...

自 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 起新增。

另请参阅

QueryEvents.before_compile()

QueryEvents.before_compile_update()

method before_compile_update(query: Query, update_context: BulkUpdate) → None

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

示例参数形式:

from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile_update')
def receive_before_compile_update(query, update_context):
    "listen for the 'before_compile_update' event"
    # ... (event handling logic) ...

自 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 中描述的对象类型相同。对象具有在 UPDATE 上下文中的一个 .values 属性,该属性是传递给 Query.update() 的参数字典。此字典可以修改以更改结果 UPDATE 语句的 VALUES 子句。

版本 1.2.17 中的新功能。

另请参阅

QueryEvents.before_compile()

QueryEvents.before_compile_delete()

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

回溯到 _Dispatch 类。

对 _Dispatch._events 进行双向处理

仪器化事件

定义了 SQLAlchemy 的类仪器化系统。

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

instrumentation.py 处理最终用户类的注册以进行状态跟踪。它与 state.py 和 attributes.py 密切交互,分别为每个实例和每个类属性仪器化。

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

对象名称 描述
InstrumentationEvents 与类仪器化事件相关的事件。
class sqlalchemy.orm.InstrumentationEvents

与类仪器化事件相关的事件。

这里的监听器支持针对任何新样式类(即任何类型的子类为 ‘type’)建立,然后对该类的事件将被触发。如果将“propagate=True”标志传递给 event.listen(),则该事件也将对该类的子类触发。

Python 的 type 内建函数也被接受为目标,当使用时会导致为所有类发出事件。

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

成员

attribute_instrument(), class_instrument(), class_uninstrument(), dispatch

类签名

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

method attribute_instrument(cls: ClassManager[_O], key: _KT, inst: _O) → None

当属性被仪器化时调用。

示例参数形式:

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 class_instrument(cls: ClassManager[_O]) → None

在给定类被检测之后调用。

示例参数形式:

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 class_uninstrument(cls: ClassManager[_O]) → None

在给定类被取消检测之前调用。

示例参数形式:

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 dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstrumentationEventsDispatch object>

参考回 _Dispatch 类。

双向反对 _Dispatch._events

相关文章
|
3月前
|
SQL 数据库 Python
SqlAlchemy 2.0 中文文档(二十六)(4)
SqlAlchemy 2.0 中文文档(二十六)
43 2
|
3月前
|
SQL 数据库连接 API
SqlAlchemy 2.0 中文文档(二十八)(1)
SqlAlchemy 2.0 中文文档(二十八)
72 2
|
3月前
|
自然语言处理 数据库 Python
SqlAlchemy 2.0 中文文档(二十六)(2)
SqlAlchemy 2.0 中文文档(二十六)
25 2
|
3月前
|
SQL 缓存 数据库连接
SqlAlchemy 2.0 中文文档(二十六)(3)
SqlAlchemy 2.0 中文文档(二十六)
32 2
|
3月前
|
SQL 缓存 数据库连接
SqlAlchemy 2.0 中文文档(二十六)(1)
SqlAlchemy 2.0 中文文档(二十六)
27 2
|
3月前
|
SQL 前端开发 关系型数据库
SqlAlchemy 2.0 中文文档(二十七)(2)
SqlAlchemy 2.0 中文文档(二十七)
28 2
|
3月前
|
SQL 缓存 前端开发
SqlAlchemy 2.0 中文文档(二十七)(5)
SqlAlchemy 2.0 中文文档(二十七)
23 2
|
3月前
|
SQL 前端开发 API
SqlAlchemy 2.0 中文文档(二十七)(1)
SqlAlchemy 2.0 中文文档(二十七)
34 1
|
3月前
|
SQL 数据库 数据库管理
SqlAlchemy 2.0 中文文档(二十七)(3)
SqlAlchemy 2.0 中文文档(二十七)
24 1
|
3月前
|
SQL 缓存 API
SqlAlchemy 2.0 中文文档(二十八)(4)
SqlAlchemy 2.0 中文文档(二十八)
59 1