РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
515 of 711 menu

Функция immediateload

Функция immediateload включает стратегию немедленной загрузки связанных объектов. При использовании этой стратегии SQLAlchemy для каждой строки основного запроса выполняет отдельный дополнительный SELECT, загружающий связанные данные. Первым параметром передаётся атрибут связи, для которого нужно применить стратегию загрузки.

Стратегия immediateload похожа на lazyload, но загрузка происходит сразу после выполнения основного запроса, а не в момент первого обращения к атрибуту. Это позволяет избежать неожиданных дополнительных запросов при работе с объектами, но приводит к эффекту N+1 - по одному SELECT на каждую связанную строку.

Синтаксис

from sqlalchemy.orm import immediateload immediateload(attribute)

Пример

Давайте создадим модели статьи и пользователя, связанные отношением один-ко-многим, и применим стратегию immediateload к связи:

from sqlalchemy import ForeignKey, String from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship class Base(DeclarativeBase): pass class User(Base): __tablename__ = 'users' id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(50)) articles: Mapped[list['Article']] = relationship( back_populates='author', lazy='immediateload', ) class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] = mapped_column(String(100)) text: Mapped[str] = mapped_column(String(500)) status: Mapped[str] = mapped_column(String(20)) num: Mapped[int] = mapped_column() author_id: Mapped[int] = mapped_column(ForeignKey('users.id')) author: Mapped['User'] = relationship(back_populates='articles')

При обращении к атрибуту articles загрузка произойдёт сразу после основного запроса к пользователям, без явного вызова дополнительного запроса:

from sqlalchemy import create_engine, select from sqlalchemy.orm import Session from models import Base, User, Article 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.scalars(select(User)).all() for user in res: print(user.name, len(user.articles))

Результат выполнения кода:

"user 2"

Пример

Давайте применим стратегию immediateload непосредственно в запросе с помощью метода options:

from sqlalchemy import create_engine, select from sqlalchemy.orm import Session, immediateload from models import Base, User, Article 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), ] session.add(user) session.commit() with Session(engine) as session: stmt = select(User).options(immediateload(User.articles)) res = session.scalars(stmt).all() for user in res: print(user.name, len(user.articles))

Результат выполнения кода:

"user 1"

Пример

Давайте посмотрим, какие SQL-запросы выполняются при стратегии immediateload, включив параметр echo:

<+python+> from sqlalchemy import create_engine, select from sqlalchemy.orm import Session, immediateload from models import Base, User, Article 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', text='text 1', status='draft', num=1), ] session.add(user) session.commit() with Session(engine) as session: stmt = select(User).options(immediateload(User.articles)) res = session.scalars(stmt).all() for user in res: print(user.name, len(user.articles)) <-python+>

Итоговые SQL-запросы:

SELECT users.id, users.name FROM users SELECT articles.id, articles.title, articles.text, articles.status, articles.num, articles.author_id FROM articles WHERE ? = articles.author_id

Смотрите также

  • функцию lazyload,
    которая откладывает загрузку связи до первого обращения
  • функцию selectinload,
    которая загружает связи одним запросом с IN
  • функцию joinedload,
    которая загружает связи через JOIN
  • функцию subqueryload,
    которая загружает связи отдельным подзапросом
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить