Значение lazy immediate
Значение lazy со значением "immediate"
задает стратегию загрузки связей, при которой
связанные объекты подгружаются сразу после
загрузки родительского объекта. В отличие от
стратегии select, которая откладывает
загрузку до момента первого обращения к атрибуту,
стратегия immediate выполняет
дополнительный SQL-запрос немедленно, как только
родительский объект был загружен. Это значение
передается параметром lazy в функцию
relationship и применяется ко всем связям
модели.
Синтаксис
relationship(..., lazy="immediate")
Пример
Давайте создадим две модели: User и
Article, связанные отношением один ко
многим. Для связи укажем стратегию
lazy="immediate":
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
articles: Mapped[list['Article']] = relationship(
back_populates='user',
lazy='immediate'
)
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]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(
back_populates='articles',
lazy='immediate'
)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
user.articles = [
Article(title='article', text='text 1', status='draft', num=1),
Article(title='article', text='text 2', status='published', num=2),
]
session.add(user)
session.commit()
with Session(engine) as session:
res = session.query(User).first()
print(res.name)
print([a.title for a in res.articles])
Результат выполнения кода:
"user"
['article', 'article']
Пример
При стратегии immediate связанные
объекты загружаются сразу, поэтому к моменту
обращения к атрибуту дополнительный SQL-запрос
уже не выполняется. Давайте посмотрим, какие
запросы отправляются в базу:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
articles: Mapped[list['Article']] = relationship(
back_populates='user',
lazy='immediate'
)
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(
back_populates='articles',
lazy='immediate'
)
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
user.articles = [Article(title='article')]
session.add(user)
session.commit()
with Session(engine) as session:
res = session.query(User).first()
print(res.name)
Итоговый SQL запрос:
SELECT users.id AS users_id, users.name AS users_name
FROM users
LIMIT ? OFFSET ?
SELECT articles.id AS articles_id, articles.title AS articles_title, articles.user_id AS articles_user_id
FROM articles
WHERE ? = articles.user_id
Смотрите также
-
функцию
relationship,
которая задает связи между моделями -
значение
lazy.select,
которое откладывает загрузку связи до первого обращения -
значение
lazy.joined,
которое загружает связь через JOIN -
значение
lazy.selectin,
которое загружает связь через отдельный SELECT IN