Release: 1.4.0b1 | Release Date: November 2, 2020

SQLAlchemy 1.4 Documentation

事件

SQLAlchemy包括一个事件API,它发布了各种钩子到SQLAlchemy核心和ORM的内部。

事件注册

订阅事件是通过单个API点发生的, listen() 功能,或者 listens_for() 装饰者。这些函数接受一个目标、一个标识要拦截的事件的字符串标识符和一个用户定义的监听函数。这两个函数的附加位置参数和关键字参数可以由特定类型的事件支持,这些事件可以为给定的事件函数指定备用接口,或者根据给定的目标提供有关辅助事件目标的说明。

事件的名称和相应侦听器函数的参数签名是从类绑定规范方法派生的,该方法绑定到文档中描述的标记类。例如,文档 PoolEvents.connect() 指示事件名称为 "connect" 用户定义的侦听器函数应接收两个位置参数:

from sqlalchemy.event import listen
from sqlalchemy.pool import Pool

def my_on_connect(dbapi_con, connection_record):
    print("New DBAPI connection:", dbapi_con)

listen(Pool, 'connect', my_on_connect)

和…一起听 listens_for() 装饰师看起来:

from sqlalchemy.event import listens_for
from sqlalchemy.pool import Pool

@listens_for(Pool, "connect")
def my_on_connect(dbapi_con, connection_record):
    print("New DBAPI connection:", dbapi_con)

命名参数样式

有许多不同的参数样式可以被侦听器函数接受。以 PoolEvents.connect() ,此功能记录为接收 dbapi_connectionconnection_record 争论。我们可以通过建立一个接受 **keyword 参数,通过传递 named=True 要么 listen()listens_for() ::

from sqlalchemy.event import listens_for
from sqlalchemy.pool import Pool

@listens_for(Pool, "connect", named=True)
def my_on_connect(**kw):
    print("New DBAPI connection:", kw['dbapi_connection'])

当使用命名参数传递时,函数参数规范中列出的名称将用作字典中的键。

命名样式按名称传递所有参数,而不考虑函数签名,因此只要名称匹配,特定参数也可以按任意顺序列出::

from sqlalchemy.event import listens_for
from sqlalchemy.pool import Pool

@listens_for(Pool, "connect", named=True)
def my_on_connect(dbapi_connection, **kw):
    print("New DBAPI connection:", dbapi_connection)
    print("Connection record:", kw['connection_record'])

以上,存在 **kw 告诉 listens_for() 该参数应按名称传递给函数,而不是按位置传递。

0.9.0 新版功能: 增加可选 named 参数调度到事件调用。

目标

这个 listen() 在目标方面功能非常灵活。它通常接受类、这些类的实例以及相关的类或对象,从中可以派生适当的目标。例如,上面提到的 "connect" 事件接受 Engine 类和对象以及 Pool 类和对象:

from sqlalchemy.event import listen
from sqlalchemy.pool import Pool, QueuePool
from sqlalchemy import create_engine
from sqlalchemy.engine import Engine
import psycopg2

def connect():
    return psycopg2.connect(user='ed', host='127.0.0.1', dbname='test')

my_pool = QueuePool(connect)
my_engine = create_engine('postgresql://ed@localhost/test')

# associate listener with all instances of Pool
listen(Pool, 'connect', my_on_connect)

# associate listener with all instances of Pool
# via the Engine class
listen(Engine, 'connect', my_on_connect)

# associate listener with my_pool
listen(my_pool, 'connect', my_on_connect)

# associate listener with my_engine.pool
listen(my_engine, 'connect', my_on_connect)

修饰语

某些侦听器允许将修饰符传递给 listen() . 这些修饰符有时为侦听器提供备用的调用签名。例如,对于ORM事件,一些事件侦听器可以有一个返回值,用于修改后续处理。默认情况下,任何侦听器都不需要返回值,而是通过传递 retval=True 可以支持此值::

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)

事件引用

sqlacalchemy core和sqlacalchemy orm都具有多种事件挂钩:

  • 核心事件 -这些在 核心事件 并且包括特定于连接池生命周期、SQL语句执行、事务生命周期以及模式创建和拆卸的事件挂钩。

  • ORM事件 -这些在 ORM事件 ,并包括特定于类和属性检测的事件挂钩、对象初始化挂钩、更改挂钩上的属性、会话状态、刷新和提交挂钩、映射器初始化、对象/结果填充和每个实例的持久挂钩。

API引用

Object Name Description

contains(target, identifier, fn)

如果给定的目标/ident/fn设置为侦听,则返回true。

listen(target, identifier, fn, *args, **kw)

为给定目标注册侦听器函数。

listens_for(target, identifier, *args, **kw)

将函数修饰为给定目标+标识符的侦听器。

remove(target, identifier, fn)

删除事件侦听器。

function sqlalchemy.event.listen(target, identifier, fn, *args, **kw)

为给定目标注册侦听器函数。

这个 listen() 函数是SQLAlchemy事件系统的主接口的一部分,记录在 事件 .

例如。::

from sqlalchemy import event
from sqlalchemy.schema import UniqueConstraint

def unique_constraint_name(const, table):
    const.name = "uq_%s_%s" % (
        table.name,
        list(const.columns)[0].name
    )
event.listen(
        UniqueConstraint,
        "after_parent_attach",
        unique_constraint_name)

给定函数也只能在第一次调用事件时使用 once 论点:

def on_config():
    do_config()

event.listen(Mapper, "before_configure", on_config, once=True)

警告

这个 once 参数并不意味着侦听器函数在第一次被调用后自动取消注册;侦听器条目将与目标对象保持关联。关联任意多个侦听器而不显式删除它们将导致内存无限增长,即使 once=True 指定。

注解

这个 listen() 不能在运行目标事件的同时调用函数。这意味着线程安全,也意味着不能从监听器函数内部为自己添加事件。要运行的事件列表存在于可变集合中,该集合在迭代期间无法更改。

事件注册和删除不打算是一个“高速”操作;它是一个配置操作。对于需要快速与大规模事件关联和解除关联的系统,请使用从单个侦听器内部处理的可变结构。

在 1.0.0 版更改: -A collections.deque() 对象现在用作事件列表的容器,该列表在迭代集合时显式禁止集合突变。

function sqlalchemy.event.listens_for(target, identifier, *args, **kw)

将函数修饰为给定目标+标识符的侦听器。

这个 listens_for() decorator是sqlAlchemy事件系统的主接口的一部分,记录在 事件 .

例如。::

from sqlalchemy import event
from sqlalchemy.schema import UniqueConstraint

@event.listens_for(UniqueConstraint, "after_parent_attach")
def unique_constraint_name(const, table):
    const.name = "uq_%s_%s" % (
        table.name,
        list(const.columns)[0].name
    )

给定函数也只能在第一次调用事件时使用 once 论点:

@event.listens_for(Mapper, "before_configure", once=True)
def on_config():
    do_config()

警告

这个 once 参数并不意味着侦听器函数在第一次被调用后自动取消注册;侦听器条目将与目标对象保持关联。关联任意多个侦听器而不显式删除它们将导致内存无限增长,即使 once=True 指定。

参见

listen() -事件监听概述

function sqlalchemy.event.remove(target, identifier, fn)

删除事件侦听器。

这里的参数应该与发送到 listen() ;由于此呼叫而进行的所有事件注册都将通过呼叫恢复。 remove() 用同样的论据。

例如。::

# if a function was registered like this...
@event.listens_for(SomeMappedClass, "before_insert", propagate=True)
def my_listener_function(*arg):
    pass

# ... it's removed like this
event.remove(SomeMappedClass, "before_insert", my_listener_function)

上面,与 SomeMappedClass 也被传播到 SomeMappedClassremove() 函数将恢复所有这些操作。

注解

这个 remove() 不能在运行目标事件的同时调用函数。这对线程安全有影响,也意味着事件不能从侦听器函数内部自行删除。要运行的事件列表存在于可变集合中,该集合在迭代期间无法更改。

事件注册和删除不打算是一个“高速”操作;它是一个配置操作。对于需要快速与大规模事件关联和解除关联的系统,请使用从单个侦听器内部处理的可变结构。

在 1.0.0 版更改: -A collections.deque() 对象现在用作事件列表的容器,该列表在迭代集合时显式禁止集合突变。

参见

listen()

function sqlalchemy.event.contains(target, identifier, fn)

如果给定的目标/ident/fn设置为侦听,则返回true。

Previous: 核心API基础 Next: 运行时检查API