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

Функция contains_eager

Функция contains_eager сообщает ORM, что связанные объекты уже загружены через явный JOIN в запросе, и не нужно выполнять отдельный запрос для связи. Первым параметром передается атрибут связи, вторым необязательным параметром можно указать псевдоним для вложенных связей. Функция полезна, когда вы сами пишете join и хотите избежать дополнительных запросов ленивой загрузки.

Синтаксис

from sqlalchemy.orm import contains_eager contains_eager(attribute, [alias])

Пример

Давайте опишем две модели: статью и пользователя-автора:

from sqlalchemy import ForeignKey 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] articles: Mapped[list['Article']] = relationship(back_populates='user') 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')

Пример

Давайте заполним базу и выполним запрос с явным join и contains_eager:

from sqlalchemy import create_engine, select from sqlalchemy.orm import Session, contains_eager 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 1', text='text 1', status='ok', num=1), Article(title='article 2', text='text 2', status='ok', num=2), ] session.add(user) session.commit() stmt = ( select(Article) .join(Article.user) .options(contains_eager(Article.user)) ) res = session.scalars(stmt).all() for article in res: print(article.title, '->', article.user.name)

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

"article 1 -> user" "article 2 -> user"

Пример

Давайте посмотрим SQL, который генерирует contains_eager - связь загружается одним запросом:

from sqlalchemy import create_engine, select from sqlalchemy.orm import Session, contains_eager from models import Base, Article engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: stmt = ( select(Article) .join(Article.user) .options(contains_eager(Article.user)) ) print(stmt)

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

SELECT articles.id, articles.title, articles.text, articles.status, articles.num, articles.user_id, users_1.id AS id_1, users_1.name FROM articles JOIN users AS users_1 ON users_1.id = articles.user_id

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

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