Событие after_insert
Событие after_insert относится к событиям
маппера и срабатывает после того, как объект
был вставлен в базу данных. Обработчик получает
первым параметром mapper, вторым -
connection, а третьим - целевой объект
target. Событие удобно использовать для
синхронизации связанных данных, логирования
или отправки уведомлений.
Синтаксис
from sqlalchemy import event
event.listen(SomeClass, 'after_insert', handler)
Также можно использовать декоратор
@event.listens_for:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_insert')
def handler(mapper, connection, target):
pass
Пример
Давайте создадим модель и повесим обработчик
на событие after_insert, чтобы вывести
сообщение после вставки объекта:
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]
@event.listens_for(Article, 'after_insert')
def after_article_insert(mapper, connection, target):
print(f'inserted article: {target.title}')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article 1')
session.add(article)
session.commit()
Результат выполнения кода:
"inserted article: article 1"
Пример
Давайте внутри обработчика after_insert
запишем значение первичного ключа в атрибут
объекта и выведем его:
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]
num: Mapped[int] = mapped_column(default=0)
@event.listens_for(Article, 'after_insert')
def set_article_num(mapper, connection, target):
target.num = target.id * 10
print(f'id={target.id}, num={target.num}')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article 1'))
session.add(Article(title='article 2'))
session.commit()
Результат выполнения кода:
"id=1, num=10"
"id=2, num=20"
Пример
Давайте через параметр connection выполним
дополнительный SQL-запрос прямо внутри обработчика
after_insert:
from sqlalchemy import create_engine, event, text
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]
@event.listens_for(Article, 'after_insert')
def log_insert(mapper, connection, target):
connection.execute(
text("INSERT INTO articles (title) VALUES (:title)"),
{'title': 'log: ' + target.title}
)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article 1'))
session.commit()
with Session(engine) as session:
res = session.query(Article.title).all()
print(res)
Результат выполнения кода:
[('article 1',), ('log: article 1',)]
Смотрите также
-
событие
before_insert,
которое срабатывает перед вставкой объекта -
событие
after_update,
которое срабатывает после обновления объекта -
функцию
listens_for,
которая регистрирует обработчик события -
функцию
remove,
которая удаляет зарегистрированный обработчик