Функция defer
Функция defer откладывает загрузку указанных
колонок модели до момента первого обращения к ним.
По умолчанию SQLAlchemy загружает все колонки объекта
сразу при выполнении запроса. Функция defer
позволяет исключить тяжелые колонки из основного
SELECT-запроса, чтобы они подгружались отдельным
запросом только при необходимости. Первым параметром
передается колонка или атрибут модели, которую нужно
отложить. Функция применяется в опциях запроса через
метод options.
Синтаксис
defer(column)
Пример
Давайте создадим модель Article и отложим
загрузку колонки text:
from sqlalchemy import create_engine, String, Text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
from sqlalchemy.orm import defer
class Base(DeclarativeBase):
pass
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(Text)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article', text='long text'))
session.commit()
res = session.query(Article).options(defer(Article.text)).first()
print(res.title)
Результат выполнения кода:
"article"
Пример
Давайте убедимся, что колонка text не попала
в основной SELECT-запрос:
from sqlalchemy import create_engine, String, Text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
from sqlalchemy.orm import defer
class Base(DeclarativeBase):
pass
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(Text)
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article', text='long text'))
session.commit()
res = session.query(Article).options(defer(Article.text)).first()
print(res.title)
Итоговый SQL запрос:
SELECT articles.id AS articles_id, articles.title AS articles_title
FROM articles
Пример
Давайте отложим сразу несколько колонок, передав их
в функцию defer по отдельности:
from sqlalchemy import create_engine, String, Text, Integer
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
from sqlalchemy.orm import defer
class Base(DeclarativeBase):
pass
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(Text)
status: Mapped[str] = mapped_column(String(50))
num: Mapped[int] = mapped_column(Integer)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(
title='article',
text='long text',
status='published',
num=1,
))
session.commit()
res = session.query(Article).options(
defer(Article.text),
defer(Article.status),
).first()
print(res.title)
print(res.text)
Результат выполнения кода:
article
long text
Смотрите также
-
функцию
undefer,
которая отменяет отложенную загрузку колонки -
функцию
load_only,
которая загружает только указанные колонки -
функцию
undefer_group,
которая снимает отложку с целой группы колонок -
функцию
with_expression,
которая подгружает произвольное SQL-выражение