Метод enable_eagerloads
Метод enable_eagerloads класса Query
управляет тем, будут ли выполняться
настройки жадной загрузки (eager loading)
связанных объектов. По умолчанию жадная
загрузка включена. Метод принимает один
обязательный параметр value - булево
значение, которое указывает, следует ли
включать жадную загрузку. Если передать
False, то все опции загрузки, такие как
joinedload и selectinload, будут
проигнорированы, и связанные объекты будут
загружаться лениво.
Метод возвращает новый объект Query,
что позволяет использовать его в цепочке
вызовов. Это особенно полезно, когда нужно
динамически отключить жадную загрузку для
конкретного запроса, не изменяя глобальные
настройки маппера.
Синтаксис
Query.enable_eagerloads(value)
Пример
Давайте создадим модель Article и
настроим жадную загрузку для связанного
объекта. Для начала определим модели:
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='author')
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'))
author: Mapped['User'] = relationship(back_populates='articles')
Теперь создадим движок, таблицы и добавим тестовые данные:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(
title='article',
text='text',
status='published',
num=1,
author=user
)
session.add(user)
session.add(article)
session.commit()
Пример
Давайте выполним запрос с жадной загрузкой по умолчанию и посмотрим, как загружается связанный объект:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, joinedload
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(
title='article',
text='text',
status='published',
num=1,
author=user
)
session.add(user)
session.add(article)
session.commit()
with Session(engine) as session:
res = session.query(Article).options(joinedload(Article.author)).all()
for article in res:
print(article.author.name)
Результат выполнения кода:
"user"
Пример
Теперь давайте отключим жадную загрузку
с помощью метода enable_eagerloads
и убедимся, что связанный объект
загружается лениво:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, joinedload
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(
title='article',
text='text',
status='published',
num=1,
author=user
)
session.add(user)
session.add(article)
session.commit()
with Session(engine) as session:
res = (
session.query(Article)
.options(joinedload(Article.author))
.enable_eagerloads(False)
.all()
)
for article in res:
print(article.author.name)
Результат выполнения кода:
"user"
В данном случае, несмотря на то что опция
joinedload была указана, она была
проигнорирована, и связанный объект был
загружен лениво при обращении к атрибуту
author.
Пример
Давайте посмотрим, как метод влияет на SQL-запрос. Сначала выполним запрос с включенной жадной загрузкой:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, joinedload
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(
title='article',
text='text',
status='published',
num=1,
author=user
)
session.add(user)
session.add(article)
session.commit()
with Session(engine) as session:
res = (
session.query(Article)
.options(joinedload(Article.author))
.all()
)
print(res)
Итоговый SQL запрос:
SELECT articles.id AS articles_id, articles.title AS articles_title, articles.text AS articles_text, articles.status AS articles_status, articles.num AS articles_num, articles.user_id AS articles_user_id, users_1.id AS users_1_id, users_1.name AS users_1_name
FROM articles LEFT OUTER JOIN users AS users_1 ON users_1.id = articles.user_id
Теперь отключим жадную загрузку:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, joinedload
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(
title='article',
text='text',
status='published',
num=1,
author=user
)
session.add(user)
session.add(article)
session.commit()
with Session(engine) as session:
res = (
session.query(Article)
.options(joinedload(Article.author))
.enable_eagerloads(False)
.all()
)
print(res)
Итоговый SQL запрос:
SELECT articles.id AS articles_id, articles.title AS articles_title, articles.text AS articles_text, articles.status AS articles_status, articles.num AS articles_num, articles.user_id AS articles_user_id
FROM articles
Как видим, при отключенной жадной загрузке JOIN не выполняется, и связанные данные загружаются отдельным запросом при обращении к атрибуту.