版本:1.1.0b2 |发布日期:2016年7月1日

SQLAlchemy 1.1文档

事件¶ T0>

SQLAlchemy包含一个事件API,它将各种各样的钩子发布到SQLAlchemy Core和ORM的内部。

New in version 0.7: The system supersedes the previous system of “extension”, “proxy”, and “listener” classes.

事件注册

通过一个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参数。We can opt to receive these arguments by name, by establishing a listener function that accepts **keyword arguments, by passing named=True to either listen() or 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参数调度到事件调用。

目标¶ T0>

The listen() function is very flexible regarding targets. 它通常接受类,这些类的实例以及从中派生出适当的目标的相关类或对象。例如,上面提到的"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(username='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)

改性剂¶ T0>

一些监听器允许修饰符被传递给listen()这些修饰符有时会为侦听器提供替代调用签名。比如对于ORM事件,一些事件监听器可以有一个返回值来修改后续的处理。默认情况下,没有监听器需要返回值,但通过传递retval=True可以支持这个值:

def validate_phone(target, value, oldvalue, initiator):
    """Strip non-numeric characters from a phone number"""

    return re.sub(r'(?![0-9])', '', value)

# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)

事件参考

SQLAlchemy Core和SQLAlchemy ORM都具有各种各样的事件挂钩:

  • Core Events - these are described in Core Events and include event hooks specific to connection pool lifecycle, SQL statement execution, transaction lifecycle, and schema creation and teardown.
  • ORM Events - these are described in ORM Events, and include event hooks specific to class and attribute instrumentation, object initialization hooks, attribute on-change hooks, session state, flush, and commit hooks, mapper initialization, object/result population, and per-instance persistence hooks.

API参考

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

为给定的目标注册一个监听器函数。

例如。:

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)

0.9.4版新增:添加once=Trueevent.listen()event.listens_for()

注意

不能在运行目标事件的同时调用listen()函数。这对线程的安全性有影响,也意味着一个事件不能从listener函数内部加入。要运行的事件列表存在于可重复集合中,在迭代过程中无法更改。

事件注册和移除不是“高速”操作;这是一个配置操作。对于需要快速关联和高级别关联事件的系统,请使用从单个侦听器内部处理的可变结构。

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

也可以看看

listens_for()

remove()

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

装饰一个函数作为给定的目标+标识符的侦听器。

例如。:

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

0.9.4版新增:添加once=Trueevent.listen()event.listens_for()

也可以看看

listen() - general description of event listening

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)

Above, the listener function associated with SomeMappedClass was also propagated to subclasses of SomeMappedClass; the remove() function will revert all of these operations.

版本0.9.0中新增。

注意

remove()函数不能在运行目标事件的同时被调用。这对线程安全性有影响,也意味着一个事件不能从listener函数内部移除。要运行的事件列表存在于可重复集合中,在迭代过程中无法更改。

事件注册和移除不是“高速”操作;这是一个配置操作。对于需要快速关联和高级别关联事件的系统,请使用从单个侦听器内部处理的可变结构。

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

也可以看看

listen()

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

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

版本0.9.0中新增。