Варианты загрузки колонн

О данном документе

В этом разделе представлены дополнительные опции, касающиеся загрузки столбцов. Используемые отображения включают колонки, хранящие большие строковые значения, для которых мы можем захотеть ограничить время загрузки.

View the ORM setup for this page. В некоторых примерах, приведенных ниже, отображатель Book будет переопределен для изменения некоторых определений столбцов.

Ограничение загрузки столбцов с помощью функции Column Deferral

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

Большинство примеров в этом разделе иллюстрируют опции загрузчика ОРМ. Это небольшие конструкции, передаваемые в метод Select.options() объекта Select, которые затем потребляются ORM при компиляции объекта в строку SQL.

Использование load_only() для сокращения загруженных столбцов

Опция загрузчика load_only() является наиболее целесообразной при загрузке объектов, когда известно, что доступ будет осуществляться только к небольшому числу столбцов. Эта опция принимает переменное количество связанных с классом объектов атрибутов, указывающих на те атрибуты, отображенные на столбцы, которые должны быть загружены, при этом все остальные атрибуты, отображенные на столбцы, не являющиеся первичным ключом, не будут входить в состав загружаемых столбцов. В приведенном ниже примере класс Book содержит столбцы .title, .summary и .cover_photo. Используя load_only(), мы можем указать ORM загружать только столбцы .title и .summary:

>>> from sqlalchemy import select
>>> from sqlalchemy.orm import load_only
>>> stmt = select(Book).options(load_only(Book.title, Book.summary))
>>> books = session.scalars(stmt).all()
{execsql}SELECT book.id, book.title, book.summary
FROM book
[...] ()
{stop}>>> for book in books:
...     print(f"{book.title}  {book.summary}")
100 Years of Krabby Patties  some long summary
Sea Catch 22  another long summary
The Sea Grapes of Wrath  yet another summary
A Nut Like No Other  some long summary
Geodesic Domes: A Retrospective  another long summary
Rocketry for Squirrels  yet another summary

Выше в операторе SELECT был опущен столбец .cover_photo и включены только столбцы .title и .summary, а также столбец первичного ключа .id; ORM, как правило, всегда получает столбцы первичного ключа, поскольку они необходимы для установления идентичности строки.

После загрузки объекта к оставшимся невыгруженным атрибутам обычно применяется поведение lazy loading, означающее, что при первом обращении к любому из них в рамках текущей транзакции будет выдан SQL-оператор для загрузки значения. Ниже при обращении к атрибуту .cover_photo выполняется оператор SELECT для загрузки его значения:

>>> img_data = books[0].cover_photo
{execsql}SELECT book.cover_photo AS book_cover_photo
FROM book
WHERE book.id = ?
[...] (1,)

Ленивые загрузки всегда выполняются с использованием Session, к которому объект находится в состоянии persistent. Если объект находится detached от любого Session, то операция завершается неудачей, вызывая исключение.

В качестве альтернативы ленивой загрузке при доступе отложенные столбцы также могут быть сконфигурированы таким образом, чтобы при обращении к ним возникало информативное исключение, независимо от состояния их вложения. При использовании конструкции load_only() это можно указать с помощью параметра load_only.raiseload. Информацию и примеры см. в разделе Использование рейсмусования для предотвращения отложенных нагрузок на колонны.

Совет

как уже отмечалось, ленивая загрузка недоступна при использовании Асинхронный ввод/вывод (asyncio).

Использование load_only() с несколькими сущностями

load_only() ограничивает себя одной сущностью, на которую ссылается список атрибутов (передача списка атрибутов, охватывающего более одной сущности, в настоящее время запрещена). В приведенном ниже примере заданная опция load_only() применяется только к сущности Book. Сущность User, которая также выбрана, не затрагивается; в результирующем операторе SELECT присутствуют все столбцы для user_account, в то время как для таблицы book присутствуют только book.id и book.title:

>>> stmt = select(User, Book).join_from(User, Book).options(load_only(Book.title))
>>> print(stmt)
{printsql}SELECT user_account.id, user_account.name, user_account.fullname,
book.id AS id_1, book.title
FROM user_account JOIN book ON user_account.id = book.owner_id

Если бы мы хотели применить опции load_only() и к User, и к Book, мы бы использовали две отдельные опции:

>>> stmt = (
...     select(User, Book)
...     .join_from(User, Book)
...     .options(load_only(User.name), load_only(Book.title))
... )
>>> print(stmt)
{printsql}SELECT user_account.id, user_account.name, book.id AS id_1, book.title
FROM user_account JOIN book ON user_account.id = book.owner_id

Использование defer() для опускания определенных столбцов

Опция defer() является более тонкой альтернативой load_only(), которая позволяет пометить один конкретный столбец как «не загружать». В приведенном ниже примере опция defer() применяется непосредственно к столбцу .cover_photo, оставляя поведение всех остальных столбцов неизменным:

>>> from sqlalchemy.orm import defer
>>> stmt = select(Book).where(Book.owner_id == 2).options(defer(Book.cover_photo))
>>> books = session.scalars(stmt).all()
{execsql}SELECT book.id, book.owner_id, book.title, book.summary
FROM book
WHERE book.owner_id = ?
[...] (2,)
{stop}>>> for book in books:
...     print(f"{book.title}: {book.summary}")
A Nut Like No Other: some long summary
Geodesic Domes: A Retrospective: another long summary
Rocketry for Squirrels: yet another summary

Как и в случае с load_only(), незагруженные столбцы по умолчанию будут загружаться сами при обращении к ним с помощью lazy loading:

>>> img_data = books[0].cover_photo
{execsql}SELECT book.cover_photo AS book_cover_photo
FROM book
WHERE book.id = ?
[...] (4,)

В одном операторе можно использовать несколько опций defer() для того, чтобы пометить несколько столбцов как отложенные.

Как и в случае с load_only(), опция defer() также включает возможность того, чтобы отложенный атрибут вызывал исключение при доступе, а не при ленивой загрузке. Это иллюстрируется в разделе Использование рейсмусования для предотвращения отложенных нагрузок на колонны.

Использование рейсмусования для предотвращения отложенных нагрузок на колонны

При использовании опций загрузчика load_only() или defer() атрибуты, помеченные в объекте как отложенные, по умолчанию ведут себя так, что при первом обращении к ним в текущей транзакции будет выдан оператор SELECT для загрузки их значения. Часто бывает необходимо предотвратить такую загрузку, а вместо этого при обращении к атрибуту выдать исключение, указывающее на то, что необходимость запроса к базе данных для этого столбца не ожидалась. Типичным сценарием является операция загрузки объектов со всеми колонками, которые, как известно, необходимы для выполнения операции, которые затем передаются на уровень представления. Любые дальнейшие SQL-операции, выполняемые в слое представления, должны быть пойманы, чтобы операция предварительной загрузки могла быть скорректирована для учета этих дополнительных данных заранее, а не для дополнительной ленивой загрузки.

Для этого случая опции defer() и load_only() включают булевский параметр defer.raiseload, который при установке значения True приведет к тому, что затронутые атрибуты будут подниматься при доступе. В приведенном ниже примере отложенный столбец .cover_photo запретит доступ к атрибуту:

>>> book = session.scalar(
...     select(Book).options(defer(Book.cover_photo, raiseload=True)).where(Book.id == 4)
... )
{execsql}SELECT book.id, book.owner_id, book.title, book.summary
FROM book
WHERE book.id = ?
[...] (4,)
{stop}>>> book.cover_photo
Traceback (most recent call last):
...
sqlalchemy.exc.InvalidRequestError: 'Book.cover_photo' is not available due to raiseload=True

При использовании load_only() для наименования определенного набора не отложенных столбцов, поведение raiseload может быть применено к оставшимся столбцам с помощью параметра load_only.raiseload, который будет применен ко всем отложенным атрибутам:

>>> session.expunge_all()
>>> book = session.scalar(
...     select(Book).options(load_only(Book.title, raiseload=True)).where(Book.id == 5)
... )
{execsql}SELECT book.id, book.title
FROM book
WHERE book.id = ?
[...] (5,)
{stop}>>> book.summary
Traceback (most recent call last):
...
sqlalchemy.exc.InvalidRequestError: 'Book.summary' is not available due to raiseload=True

Примечание

Пока невозможно смешивать в одном операторе опции load_only() и defer(), относящиеся к одной и той же сущности, чтобы изменить поведение raiseload определенных атрибутов; в настоящее время это приведет к неопределенному поведению атрибутов при загрузке.

См.также

Функция defer.raiseload представляет собой версию на уровне столбцов той же функции «raiseload», которая доступна для отношений. О «raiseload» с отношениями см. раздел Предотвращение нежелательных «ленивых» загрузок с помощью raiseload в Техники загрузки отношений данного руководства.

Настройка отсрочки колонок в сопоставлениях

Функциональность defer() доступна в качестве поведения по умолчанию для отображаемых колонок, что может быть целесообразно для колонок, которые не должны загружаться безусловно при каждом запросе. Для настройки используйте параметр mapped_column.deferred в mapped_column(). В приведенном ниже примере показано отображение для Book, которое применяет отсрочку столбцов по умолчанию к столбцам summary и cover_photo:

>>> class Book(Base):
...     __tablename__ = "book"
...     id: Mapped[int] = mapped_column(primary_key=True)
...     owner_id: Mapped[int] = mapped_column(ForeignKey("user_account.id"))
...     title: Mapped[str]
...     summary: Mapped[str] = mapped_column(Text, deferred=True)
...     cover_photo: Mapped[bytes] = mapped_column(LargeBinary, deferred=True)
...
...     def __repr__(self) -> str:
...         return f"Book(id={self.id!r}, title={self.title!r})"

При использовании приведенного выше отображения запросы к Book автоматически не будут включать столбцы summary и cover_photo:

>>> book = session.scalar(select(Book).where(Book.id == 2))
{execsql}SELECT book.id, book.owner_id, book.title
FROM book
WHERE book.id = ?
[...] (2,)

Как и в случае со всеми отложенными атрибутами, поведение по умолчанию при первом обращении к отложенным атрибутам загруженного объекта заключается в том, что они будут lazy load своим значением:

>>> img_data = book.cover_photo
{execsql}SELECT book.cover_photo AS book_cover_photo
FROM book
WHERE book.id = ?
[...] (2,)

Как и в случае с опциями загрузчика defer() и load_only(), отсрочка на уровне картографа также включает в себя возможность поведения raiseload, а не ленивой загрузки, когда в операторе отсутствуют другие опции. Это позволяет создать отображение, в котором определенные колонки не будут загружаться по умолчанию, а также никогда не будут загружаться лениво без явных директив, используемых в операторе. О том, как настроить и использовать это поведение, читайте в разделе Настройка поведения «raiseload» на уровне картографа.

Использование deferred() для императивных отображателей, отображаемых SQL-выражений

Функция deferred() - это ранняя, более общего назначения директива отображения «отложенный столбец», которая предшествовала введению в SQLAlchemy конструкции mapped_column().

deferred() используется при настройке ORM-мапперов и принимает произвольные SQL-выражения или объекты Column. Поэтому его удобно использовать с недекларативным imperative mappings, передавая его в словарь map_imperatively.properties:

from sqlalchemy import Blob
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
from sqlalchemy.orm import registry

mapper_registry = registry()

book_table = Table(
    "book",
    mapper_registry.metadata,
    Column("id", Integer, primary_key=True),
    Column("title", String(50)),
    Column("summary", Text),
    Column("cover_image", Blob),
)


class Book:
    pass


mapper_registry.map_imperatively(
    Book,
    book_table,
    properties={
        "summary": deferred(book_table.c.summary),
        "cover_image": deferred(book_table.c.cover_image),
    },
)

deferred() также может использоваться вместо column_property(), когда отображаемые SQL-выражения должны загружаться на отложенной основе:

from sqlalchemy.orm import deferred


class User(Base):
    __tablename__ = "user"

    id: Mapped[int] = mapped_column(primary_key=True)
    firstname: Mapped[str] = mapped_column()
    lastname: Mapped[str] = mapped_column()
    fullname: Mapped[str] = deferred(firstname + " " + lastname)

Использование undefer() для «нетерпеливой» загрузки отложенных столбцов

Если в отображениях колонки по умолчанию настроены на отсрочку, то опция undefer() приведет к тому, что любая колонка, которая обычно отсрочена, будет отсрочена, т.е. будет загружена вперед со всеми остальными колонками отображения. Например, мы можем применить опцию undefer() к столбцу Book.summary, который в предыдущем отображении указан как отложенный:

>>> from sqlalchemy.orm import undefer
>>> book = session.scalar(select(Book).where(Book.id == 2).options(undefer(Book.summary)))
{execsql}SELECT book.id, book.owner_id, book.title, book.summary
FROM book
WHERE book.id = ?
[...] (2,)

Теперь столбец Book.summary был загружен с нетерпением, и к нему можно обращаться без дополнительного SQL:

>>> print(book.summary)
another long summary

Загрузка отложенных столбцов в группах

Обычно, когда столбец отображается с помощью параметра mapped_column(deferred=True), при обращении к отложенному атрибуту на объекте будет выдан SQL для загрузки только этого конкретного столбца и никаких других, даже если в отображении есть другие столбцы, которые также помечены как отложенные. В случае, когда отложенный атрибут является частью группы атрибутов, которые должны загружаться одновременно, вместо того, чтобы выдавать SQL для каждого атрибута в отдельности, можно использовать параметр mapped_column.deferred_group, который принимает произвольную строку, определяющую общую группу столбцов, которые должны быть не отложены:

>>> class Book(Base):
...     __tablename__ = "book"
...     id: Mapped[int] = mapped_column(primary_key=True)
...     owner_id: Mapped[int] = mapped_column(ForeignKey("user_account.id"))
...     title: Mapped[str]
...     summary: Mapped[str] = mapped_column(
...         Text, deferred=True, deferred_group="book_attrs"
...     )
...     cover_photo: Mapped[bytes] = mapped_column(
...         LargeBinary, deferred=True, deferred_group="book_attrs"
...     )
...
...     def __repr__(self) -> str:
...         return f"Book(id={self.id!r}, title={self.title!r})"

При использовании приведенного выше отображения обращение либо к summary, либо к cover_photo приведет к одновременной загрузке обоих столбцов с помощью одного оператора SELECT:

>>> book = session.scalar(select(Book).where(Book.id == 2))
{execsql}SELECT book.id, book.owner_id, book.title
FROM book
WHERE book.id = ?
[...] (2,)
{stop}>>> img_data, summary = book.cover_photo, book.summary
{execsql}SELECT book.summary AS book_summary, book.cover_photo AS book_cover_photo
FROM book
WHERE book.id = ?
[...] (2,)

Разложение по группам с помощью undefer_group()

Если отложенные колонки сконфигурированы с помощью опции mapped_column.deferred_group, как это было представлено в предыдущем разделе, то вся группа может быть указана для нетерпеливой загрузки с помощью опции undefer_group(), передавая строковое имя группы, которая должна быть нетерпеливо загружена:

>>> from sqlalchemy.orm import undefer_group
>>> book = session.scalar(
...     select(Book).where(Book.id == 2).options(undefer_group("book_attrs"))
... )
{execsql}SELECT book.id, book.owner_id, book.title, book.summary, book.cover_photo
FROM book
WHERE book.id = ?
[...] (2,)

Оба варианта summary и cover_photo доступны без дополнительной нагрузки:

>>> img_data, summary = book.cover_photo, book.summary

Отмена разделения на подстановочные знаки

Большинство опций ORM-загрузчика допускают использование подстановочного символа, обозначаемого "*", который указывает, что опция должна применяться ко всем соответствующим атрибутам. Если в отображении имеется ряд отложенных столбцов, то все такие столбцы могут быть отложены сразу, без использования имени группы, путем указания подстановочного символа:

>>> book = session.scalar(select(Book).where(Book.id == 3).options(undefer("*")))
{execsql}SELECT book.id, book.owner_id, book.title, book.summary, book.cover_photo
FROM book
WHERE book.id = ?
[...] (3,)

Настройка поведения «raiseload» на уровне картографа

Поведение «raiseload», впервые представленное в Использование рейсмусования для предотвращения отложенных нагрузок на колонны, также может быть применено в качестве поведения по умолчанию на уровне картографа, используя параметр mapped_column.deferred_raiseload в mapped_column(). При использовании этого параметра затронутые столбцы будут подниматься при доступе во всех случаях, если они явно не «отложены» с помощью undefer() или load_only() во время запроса:

>>> class Book(Base):
...     __tablename__ = "book"
...     id: Mapped[int] = mapped_column(primary_key=True)
...     owner_id: Mapped[int] = mapped_column(ForeignKey("user_account.id"))
...     title: Mapped[str]
...     summary: Mapped[str] = mapped_column(Text, deferred=True, deferred_raiseload=True)
...     cover_photo: Mapped[bytes] = mapped_column(
...         LargeBinary, deferred=True, deferred_raiseload=True
...     )
...
...     def __repr__(self) -> str:
...         return f"Book(id={self.id!r}, title={self.title!r})"

При использовании приведенного выше отображения столбцы .summary и .cover_photo по умолчанию не загружаются:

>>> book = session.scalar(select(Book).where(Book.id == 2))
{execsql}SELECT book.id, book.owner_id, book.title
FROM book
WHERE book.id = ?
[...] (2,)
{stop}>>> book.summary
Traceback (most recent call last):
...
sqlalchemy.exc.InvalidRequestError: 'Book.summary' is not available due to raiseload=True

Атрибуты могут быть загружены только путем переопределения их поведения во время запроса, обычно с помощью undefer() или undefer_group(), реже defer(). В приведенном ниже примере применяется undefer('*') для отмены отмены отмены всех атрибутов, а также используется Заполнить существующие для обновления опций загрузчика уже загруженного объекта:

>>> book = session.scalar(
...     select(Book)
...     .where(Book.id == 2)
...     .options(undefer("*"))
...     .execution_options(populate_existing=True)
... )
{execsql}SELECT book.id, book.owner_id, book.title, book.summary, book.cover_photo
FROM book
WHERE book.id = ?
[...] (2,)
{stop}>>> book.summary
'another long summary'

Загрузка произвольных SQL-выражений в объекты

Как уже говорилось Выбор сущностей и атрибутов ORM и в других статьях, конструкция select() может быть использована для загрузки произвольных SQL-выражений в набор результатов. Например, если мы хотим создать запрос, который загружает User объектов, но при этом включает подсчет количества книг, принадлежащих каждому User, мы можем использовать func.count(Book.id) для добавления столбца «count» в запрос, который включает JOIN к Book, а также GROUP BY owner id. В результате будут получены объекты Row, содержащие по две записи: одну для User и одну для func.count(Book.id):

>>> from sqlalchemy import func
>>> stmt = select(User, func.count(Book.id)).join_from(User, Book).group_by(Book.owner_id)
>>> for user, book_count in session.execute(stmt):
...     print(f"Username: {user.name}  Number of books: {book_count}")
{execsql}SELECT user_account.id, user_account.name, user_account.fullname,
count(book.id) AS count_1
FROM user_account JOIN book ON user_account.id = book.owner_id
GROUP BY book.owner_id
[...] ()
{stop}Username: spongebob  Number of books: 3
Username: sandy  Number of books: 3

User User Session.scalars() func.count(Book.id) User column_property() with_expression() query_expression() I

with_expression() query_expression() User.book_count User None T

>>> from sqlalchemy.orm import query_expression
>>> class User(Base):
...     __tablename__ = "user_account"
...     id: Mapped[int] = mapped_column(primary_key=True)
...     name: Mapped[str]
...     fullname: Mapped[Optional[str]]
...     book_count: Mapped[int] = query_expression()
...
...     def __repr__(self) -> str:
...         return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"

User.book_count with_expression() User W

>>> from sqlalchemy.orm import with_expression
>>> stmt = (
...     select(User)
...     .join_from(User, Book)
...     .group_by(Book.owner_id)
...     .options(with_expression(User.book_count, func.count(Book.id)))
... )
>>> for user in session.scalars(stmt):
...     print(f"Username: {user.name}  Number of books: {user.book_count}")
{execsql}SELECT count(book.id) AS count_1, user_account.id, user_account.name,
user_account.fullname
FROM user_account JOIN book ON user_account.id = book.owner_id
GROUP BY book.owner_id
[...] ()
{stop}Username: spongebob  Number of books: 3
Username: sandy  Number of books: 3

func.count(Book.id) select() with_expression() A

:func:`.query_expression`T

  • with_expression() None query_expression.default_expr O

  • with_expression() Заполнить существующие A T

    # load the first A
    obj = session.scalars(select(A).order_by(A.id)).first()
    
    # load the same A with an option; expression will **not** be applied
    # to the already-loaded object
    obj = session.scalars(select(A).options(with_expression(A.expr, some_expr))).first()

    :ref:`orm_queryguide_populate_existing`T

    obj = session.scalars(
        select(A)
        .options(with_expression(A.expr, some_expr))
        .execution_options(populate_existing=True)
    ).first()
  • with_expression() Session.expire() Session.commit() None T

  • with_expression() ``with_expression()``U <

  • Атрибут mapped не может быть применен к другим частям запроса, таким как предложение WHERE, предложение ORDER BY, и использовать выражение ad-hoc; то есть это не будет работать:

    # can't refer to A.expr elsewhere in the query
    stmt = (
        select(A)
        .options(with_expression(A.expr, A.x + A.y))
        .filter(A.expr > 5)
        .order_by(A.expr)
    )

    ``A.expr``T

    # assign desired expression up front, then refer to that in
    # the query
    a_expr = A.x + A.y
    stmt = (
        select(A)
        .options(with_expression(A.expr, a_expr))
        .filter(a_expr > 5)
        .order_by(a_expr)
    )

``with_expression()``U

with_expression() select() T

query_expression() with_expression() I

select() A expr union_all() A Выбор сущностей из UNION и других операций над множествами with_expression() A I

>>> from sqlalchemy import union_all
>>> s1 = (
...     select(User, func.count(Book.id).label("book_count"))
...     .join_from(User, Book)
...     .where(User.name == "spongebob")
... )
>>> s2 = (
...     select(User, func.count(Book.id).label("book_count"))
...     .join_from(User, Book)
...     .where(User.name == "sandy")
... )
>>> union_stmt = union_all(s1, s2)
>>> orm_stmt = (
...     select(User)
...     .from_statement(union_stmt)
...     .options(with_expression(User.book_count, union_stmt.selected_columns.book_count))
... )
>>> for user in session.scalars(orm_stmt):
...     print(f"Username: {user.name}  Number of books: {user.book_count}")
{execsql}SELECT user_account.id, user_account.name, user_account.fullname, count(book.id) AS book_count
FROM user_account JOIN book ON user_account.id = book.owner_id
WHERE user_account.name = ?
UNION ALL
SELECT user_account.id, user_account.name, user_account.fullname, count(book.id) AS book_count
FROM user_account JOIN book ON user_account.id = book.owner_id
WHERE user_account.name = ?
[...] ('spongebob', 'sandy'){stop}
Username: spongebob  Number of books: 3
Username: sandy  Number of books: 3

API загрузки столбцов

Object Name Description

defer(key, *addl_attrs, [raiseload])

Указывает, что данный атрибут, ориентированный на столбец, должен быть отложенным, т.е. не загружаться до обращения к нему.

deferred(column, *additional_columns, [group, raiseload, comparator_factory, init, repr, default, default_factory, compare, kw_only, active_history, expire_on_flush, info, doc])

Укажите отображаемый атрибут на основе столбцов, который по умолчанию не будет загружаться, если к нему нет доступа.

load_only(*attrs, [raiseload])

Указывает, что для конкретной сущности следует загружать только заданный список имен атрибутов, основанных на столбцах; все остальные будут отложены.

query_expression([default_expr], *, [repr, compare, expire_on_flush, info, doc])

Укажите атрибут, который заполняется из SQL-выражения во время запроса.

undefer(key, *addl_attrs)

Указывает, что данный атрибут, ориентированный на столбец, должен быть нераспределенным, например, указанным в операторе SELECT для сущности в целом.

undefer_group(name)

Укажите, что столбцы внутри заданного имени отложенной группы должны быть не отложены.

with_expression(key, expression)

Применить специальное SQL-выражение к атрибуту «отложенное выражение».

function sqlalchemy.orm.defer(key: Union[str, QueryableAttribute[Any]], *addl_attrs: Union[str, QueryableAttribute[Any]], raiseload: bool = False) _AbstractLoad

Указывает, что данный атрибут, ориентированный на столбец, должен быть отложенным, т.е. не загружаться до обращения к нему.

Эта функция является частью интерфейса Load и поддерживает как цепочку методов, так и автономную работу.

например:

from sqlalchemy.orm import defer

session.query(MyClass).options(
    defer(MyClass.attribute_one),
    defer(MyClass.attribute_two)
)

:func:`_orm.defaultload`T

session.query(MyClass).options(
    defaultload(MyClass.someattr).defer(RelatedClass.some_column)
)

:meth:`_orm.Load.options`M

session.query(MyClass).options(
    defaultload(MyClass.someattr).options(
        defer(RelatedClass.some_column),
        defer(RelatedClass.some_other_column),
        defer(RelatedClass.another_column)
    )
)
Параметры:
  • key – Атрибут, подлежащий отсрочке.

  • raiseload – :class:`.InvalidRequestError`r

Добавлено в версии 1.4.

function sqlalchemy.orm.deferred(column: _ORMColumnExprArgument[_T], *additional_columns: _ORMColumnExprArgument[Any], group: Optional[str] = None, raiseload: bool = False, comparator_factory: Optional[Type[PropComparator[_T]]] = None, init: Union[_NoArg, bool] = _NoArg.NO_ARG, repr: Union[_NoArg, bool] = _NoArg.NO_ARG, default: Optional[Any] = _NoArg.NO_ARG, default_factory: Union[_NoArg, Callable[[], _T]] = _NoArg.NO_ARG, compare: Union[_NoArg, bool] = _NoArg.NO_ARG, kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG, active_history: bool = False, expire_on_flush: bool = True, info: Optional[_InfoType] = None, doc: Optional[str] = None) MappedSQLExpression[_T]

Укажите отображаемый атрибут на основе столбцов, который по умолчанию не будет загружаться, если к нему нет доступа.

mapped_column() deferred() mapped_column.deferred W

Параметры:
  • *columns – :class:`_schema.Column`c

  • raiseload – boolean, если True, то указывает, что при выполнении операции загрузки должно быть вызвано исключение. … versionadded:: 1.4

:func:`_orm.column_property`A

function sqlalchemy.orm.query_expression(default_expr: _ORMColumnExprArgument[_T] = <sqlalchemy.sql.elements.Null object>, *, repr: Union[_NoArg, bool] = _NoArg.NO_ARG, compare: Union[_NoArg, bool] = _NoArg.NO_ARG, expire_on_flush: bool = True, info: Optional[_InfoType] = None, doc: Optional[str] = None) MappedSQLExpression[_T]

Укажите атрибут, который заполняется из SQL-выражения во время запроса.

Параметры:

default_expr – :func:`_orm.with_expression`O

Добавлено в версии 1.2.

См.также

:ref:`orm_queryguide_with_expression`<

function sqlalchemy.orm.load_only(*attrs: Union[str, QueryableAttribute[Any]], raiseload: bool = False) _AbstractLoad

Указывает, что для конкретной сущности следует загружать только заданный список имен атрибутов, основанных на столбцах; все остальные будут отложены.

Эта функция является частью интерфейса Load и поддерживает как цепочку методов, так и автономную работу.

User name fullname E

session.query(User).options(load_only(User.name, User.fullname))

User.addresses -> Address User.addresses Address email_address E

session.query(User).options(
    subqueryload(User.addresses).load_only(Address.email_address)
)

:class:`_orm.Load`F

stmt = select(User, Address).join(User.addresses).options(
            Load(User).load_only(User.name, User.fullname),
            Load(Address).load_only(Address.email_address)
        )
Параметры:
  • *attrs – Атрибуты должны быть загружены, все остальные будут отложены.

  • raiseload – :class:`.InvalidRequestError`r

Параметры:
  • *attrs – Атрибуты должны быть загружены, все остальные будут отложены.

  • raiseload – :class:`.InvalidRequestError`r

function sqlalchemy.orm.undefer(key: Union[str, QueryableAttribute[Any]], *addl_attrs: Union[str, QueryableAttribute[Any]]) _AbstractLoad

Указывает, что данный атрибут, ориентированный на столбец, должен быть нераспределенным, например, указанным в операторе SELECT для сущности в целом.

:func:`.deferred`T

Эта функция является частью интерфейса Load и поддерживает как цепочку методов, так и автономную работу.

Примеры:

# undefer two columns
session.query(MyClass).options(
    undefer(MyClass.col1), undefer(MyClass.col2)
)

# undefer all columns specific to a single class using Load + *
session.query(MyClass, MyOtherClass).options(
    Load(MyClass).undefer("*"))

# undefer a column on a related object
session.query(MyClass).options(
    defaultload(MyClass.items).undefer(MyClass.text))
Параметры:

key – Атрибут, который должен быть отложен.

function sqlalchemy.orm.undefer_group(name: str) _AbstractLoad

Укажите, что столбцы внутри заданного имени отложенной группы должны быть не отложены.

:func:`.deferred`T

E

session.query(MyClass).options(undefer_group("large_attrs"))

:func:`_orm.defaultload`T

session.query(MyClass).options(
    defaultload("someattr").undefer_group("large_attrs"))
function sqlalchemy.orm.with_expression(key: _AttrType, expression: _ColumnExpressionArgument[Any]) _AbstractLoad

Применить специальное SQL-выражение к атрибуту «отложенное выражение».

:func:`_orm.query_expression`T

Например:

stmt = select(SomeClass).options(
    with_expression(SomeClass.x_y_expr, SomeClass.x + SomeClass.y)
)

Добавлено в версии 1.2.

Параметры:
  • key – Атрибут, который необходимо заполнить

  • expr – SQL-выражение, которое должно быть применено к атрибуту.

См.также

:ref:`orm_queryguide_with_expression`<

Вернуться на верх