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

Функция selectinload

Функция selectinload выполняет жадную загрузку связанных объектов, отправляя дополнительный SELECT-запрос с условием IN по первичным ключам родительских записей. Первым параметром функция принимает атрибут отношения, который нужно загрузить. В отличие от joinedload, она не использует JOIN и поэтому не раздувает результирующий набор при загрузке коллекций.

Синтаксис

selectinload(attr)

Пример

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

from sqlalchemy import create_engine, ForeignKey, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] comments: Mapped[list['Comment']] = relationship(back_populates='article') class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: article = Article(title='article', comments=[ Comment(text='article'), Comment(text='article'), ]) session.add(article) session.commit()

Пример

Давайте загрузим статьи вместе с комментариями через selectinload:

from sqlalchemy import create_engine, ForeignKey, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session, selectinload class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] comments: Mapped[list['Comment']] = relationship(back_populates='article') class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add(Article(title='article', comments=[ Comment(text='article'), Comment(text='article'), ])) session.commit() stmt = select(Article).options(selectinload(Article.comments)) res = session.scalars(stmt).all() for article in res: print(article.title, [c.text for c in article.comments])

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

"article ['article', 'article']"

Пример

Давайте посмотрим, какие SQL-запросы выполняет selectinload при загрузке коллекции:

from sqlalchemy import create_engine, ForeignKey, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session, selectinload class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] comments: Mapped[list['Comment']] = relationship(back_populates='article') class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:', echo=True) Base.metadata.create_all(engine) with Session(engine) as session: session.add(Article(title='article', comments=[ Comment(text='article'), Comment(text='article'), ])) session.commit() stmt = select(Article).options(selectinload(Article.comments)) res = session.scalars(stmt).all()

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

SELECT articles.id, articles.title FROM articles SELECT comments.article_id AS comments_article_id, comments.id AS comments_id, comments.text AS comments_text FROM comments WHERE comments.article_id IN (?)

Пример

Давайте загрузим связанный объект со стороны многих-к-одному через selectinload:

from sqlalchemy import create_engine, ForeignKey, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session, selectinload class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] comments: Mapped[list['Comment']] = relationship(back_populates='article') class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add(Article(title='article', comments=[ Comment(text='article'), ])) session.commit() stmt = select(Comment).options(selectinload(Comment.article)) res = session.scalars(stmt).all() for comment in res: print(comment.text, comment.article.title)

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

"article article"

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

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