Функция reconstructor
Функция reconstructor является декоратором
для методов ORM-модели. Она помечает метод,
который будет вызван сразу после того, как
SQLAlchemy создаст экземпляр объекта на основе
данных, полученных из базы. Это позволяет
выполнить дополнительную инициализацию полей
или вычислить значения, которые не хранятся
в таблице. Декоратор не принимает параметров,
а метод, к которому он применяется, должен
принимать только self.
Синтаксис
from sqlalchemy.orm import reconstructor
@reconstructor
def method_name(self):
...
Пример
Давайте создадим модель Article с методом,
помеченным reconstructor, который при
восстановлении объекта из базы заполняет
дополнительный атрибут:
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, reconstructor, 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]
@reconstructor
def init_on_load(self):
self.label = f'{self.title} ({self.status})'
Пример
Теперь создадим таблицу, добавим запись и
извлечём её из базы, чтобы увидеть работу
метода init_on_load:
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, reconstructor, 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]
@reconstructor
def init_on_load(self):
self.label = f'{self.title} ({self.status})'
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(
title='article',
text='some text',
status='published',
num=1,
)
session.add(article)
session.commit()
with Session(engine) as session:
res = session.get(Article, 1)
print(res.label)
Результат выполнения кода:
"article (published)"
Пример
Метод reconstructor также вызывается
при загрузке нескольких объектов через
select. Проверим это:
from sqlalchemy import create_engine, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, reconstructor, 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]
@reconstructor
def init_on_load(self):
self.label = f'{self.title} ({self.status})'
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add_all([
Article(title='article 1', text='text 1', status='draft', num=1),
Article(title='article 2', text='text 2', status='published', num=2),
])
session.commit()
with Session(engine) as session:
res = session.scalars(select(Article)).all()
for article in res:
print(article.label)
Результат выполнения кода:
"article 1 (draft)"
"article 2 (published)"
Смотрите также
-
класс
DeclarativeBase,
который является базой для декларативных моделей -
функцию
mapped_column,
которая описывает колонку таблицы -
функцию
validates,
которая добавляет валидацию атрибутов -
функцию
object_session,
которая возвращает сессию для объекта