События

SQLAlchemy включает в себя API событий, который публикует широкий спектр крючков во внутренние компоненты как SQLAlchemy Core, так и 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_connection и connection_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)

Ссылка на событие

Как SQLAlchemy Core, так и SQLAlchemy ORM имеют широкий спектр крючков событий:

  • Основные события - они описаны в Основные события и включают крючки событий, специфичных для жизненного цикла пула соединений, выполнения операторов SQL, жизненного цикла транзакции, создания и разрушения схемы.

  • ORM Events - они описаны в События ОРМ, и включают в себя крючки событий, специфичные для инструментов класса и атрибутов, крючки инициализации объектов, крючки изменения атрибутов, крючки состояния сессии, смыва и фиксации, крючки инициализации маппера, регистрации объектов/результатов, и крючки персистентности для каждого экземпляра.

Справочник по API

Вернуться на верх