Событие after_update
Событие after_update относится к секции
event и срабатывает после того, как
SQLAlchemy выполнит UPDATE-запрос к базе данных
для конкретного объекта. Обработчик получает
первым параметром целевой объект mapper,
вторым - connection, третьим - сам
экземпляр модели target. Событие удобно
использовать для аудита изменений, логирования
или синхронизации связанных данных.
Синтаксис
from sqlalchemy import event
@event.listens_for(SomeModel, 'after_update')
def receive_after_update(mapper, connection, target):
pass
Пример
Давайте создадим модель Article и
подпишемся на событие after_update,
чтобы вывести заголовок измененной статьи:
from sqlalchemy import create_engine, event
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
text: Mapped[str]
status: Mapped[str]
num: Mapped[int]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
@event.listens_for(Article, 'after_update')
def receive_after_update(mapper, connection, target):
print('updated:', target.title)
with Session(engine) as session:
article = Article(title='article', text='text', status='draft', num=1)
session.add(article)
session.commit()
article.title = 'article 2'
session.commit()
Результат выполнения кода:
"updated: article 2"
Пример
Давайте в обработчике события воспользуемся
параметром connection и выведем
информацию о соединении:
from sqlalchemy import create_engine, event
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
text: Mapped[str]
status: Mapped[str]
num: Mapped[int]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
@event.listens_for(Article, 'after_update')
def receive_after_update(mapper, connection, target):
print('target id:', target.id)
print('connection:', connection.engine.url)
with Session(engine) as session:
article = Article(title='article', text='text', status='draft', num=1)
session.add(article)
session.commit()
article.status = 'published'
session.commit()
Результат выполнения кода:
"target id: 1"
"connection: sqlite:///:memory:"
Пример
Давайте проверим, что событие срабатывает только при реальном изменении данных, а не при простом коммите без правок:
from sqlalchemy import create_engine, event
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
text: Mapped[str]
status: Mapped[str]
num: Mapped[int]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
counter = {'updates': 0}
@event.listens_for(Article, 'after_update')
def receive_after_update(mapper, connection, target):
counter['updates'] += 1
with Session(engine) as session:
article = Article(title='article', text='text', status='draft', num=1)
session.add(article)
session.commit()
session.commit()
print('updates:', counter['updates'])
article.num = 2
session.commit()
print('updates:', counter['updates'])
Результат выполнения кода:
"updates: 0"
"updates: 1"
Смотрите также
-
событие
before_update,
которое срабатывает перед UPDATE-запросом -
событие
after_insert,
которое срабатывает после INSERT-запроса -
событие
after_delete,
которое срабатывает после DELETE-запроса -
функцию
listens_for,
которая регистрирует обработчик события