Метод populate_existing
Метод populate_existing класса Query
заставляет SQLAlchemy обновить объекты, которые уже
присутствуют в текущей сессии, свежими данными из
базы данных. Обычно при выполнении запроса ORM
возвращает уже существующий объект из identity map
сессии, не перезаписывая его атрибуты значениями
из строки результата. Метод populate_existing
отменяет это поведение и принудительно перезаписывает
состояние объектов. Метод не принимает параметров
и возвращает новый объект Query.
Синтаксис
query.populate_existing()
Пример
Давайте создадим модель и убедимся, что без вызова
populate_existing ORM возвращает устаревший
объект из сессии:
from sqlalchemy import create_engine, String
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] = mapped_column(String(50))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(id=1, title='article'))
session.commit()
with Session(engine) as session:
res = session.query(Article).first()
print(res.title)
session.execute(
Article.__table__.update().values(title='updated')
)
session.commit()
res = session.query(Article).first()
print(res.title)
Результат выполнения кода:
"article"
"article"
Пример
Теперь применим populate_existing, чтобы
получить актуальные данные из базы:
from sqlalchemy import create_engine, String
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] = mapped_column(String(50))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(id=1, title='article'))
session.commit()
with Session(engine) as session:
res = session.query(Article).first()
print(res.title)
session.execute(
Article.__table__.update().values(title='updated')
)
session.commit()
res = session.query(Article).populate_existing().first()
print(res.title)
Результат выполнения кода:
"article"
"updated"
Пример
Метод удобно комбинировать с all для
обновления списка объектов сразу:
from sqlalchemy import create_engine, String
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] = mapped_column(String(50))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add_all([
Article(id=1, title='article 1'),
Article(id=2, title='article 2'),
])
session.commit()
with Session(engine) as session:
res = session.query(Article).all()
print([a.title for a in res])
session.execute(
Article.__table__.update().values(title='changed')
)
session.commit()
res = session.query(Article).populate_existing().all()
print([a.title for a in res])
Результат выполнения кода:
['article 1', 'article 2']
['changed', 'changed']
Смотрите также
-
класс
Query,
который представляет ORM-запрос к базе данных -
метод
all,
который возвращает все результаты запроса -
метод
options,
который задает опции загрузки объектов -
метод
with_for_update,
который блокирует строки при чтении