Функция lazyload
Функция lazyload задает стратегию
отложенной загрузки для указанной связи.
При такой стратегии связанные объекты
загружаются из базы данных только в момент
первого обращения к атрибуту связи, а не
сразу при загрузке родительского объекта.
Функция принимает один параметр - атрибут
связи, для которого нужно применить стратегию,
и возвращает объект загрузчика, который
можно передать в метод options.
Синтаксис
lazyload(attribute)
Пример
Давайте создадим две связанные модели и
применим стратегию lazyload к связи
articles:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
from sqlalchemy.orm import lazyload
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='author')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
author_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
author: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
user.articles = [Article(title='article')]
session.add(user)
session.commit()
res = session.query(User).options(lazyload(User.articles)).first()
print(res.articles)
Результат выполнения кода:
[Article(id=1, title='article', author_id=1)]
Пример
Давайте убедимся, что при стратегии
lazyload связанные объекты не
загружаются до первого обращения к атрибуту:
<+python+>
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
from sqlalchemy.orm import lazyload
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='author')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
author_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
author: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
user.articles = [Article(title='article')]
session.add(user)
session.commit()
session.expunge_all()
res = session.query(User).options(lazyload(User.articles)).first()
print('before access')
print(res.articles)
print('after access')
<-python+>
Результат выполнения кода:
"before access"
[Article(id=1, title='article', author_id=1)]
"after access"
Смотрите также
-
функцию
selectinload,
которая загружает связи отдельным SELECT-запросом -
функцию
joinedload,
которая загружает связи через JOIN -
функцию
subqueryload,
которая загружает связи через подзапрос -
функцию
noload,
которая полностью отключает загрузку связи