Значение lazy noload
Значение noload используется в параметре lazy
функции relationship и указывает
SQLAlchemy никогда не загружать связанные объекты
автоматически. При обращении к атрибуту связи
возвращается пустой список или None,
а SQL-запрос к связанной таблице не выполняется.
Этот режим удобен, когда связанные данные
заведомо не нужны в текущем сценарии.
Синтаксис
relationship(..., lazy='noload')
Пример
Давайте создадим две связанные модели
и настроим связь со значением noload:
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(lazy='noload')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user', articles=[Article(title='article')])
session.add(user)
session.commit()
with Session(engine) as session:
user = session.get(User, 1)
print(user.articles)
Результат выполнения кода:
[]
Пример
Давайте убедимся, что при обращении к связи
со значением noload SQL-запрос
к связанной таблице не выполняется:
from sqlalchemy import create_engine, ForeignKey, event
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(lazy='noload')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user', articles=[Article(title='article')])
session.add(user)
session.commit()
queries = []
@event.listens_for(engine, 'before_cursor_execute')
def track(conn, cursor, statement, params, context, executemany):
queries.append(statement)
with Session(engine) as session:
user = session.get(User, 1)
queries.clear()
_ = user.articles
print('queries:', len(queries))
Результат выполнения кода:
"queries: 0"
Как видно, при обращении к user.articles
не выполняется ни одного SQL-запроса.
Смотрите также
-
функцию
relationship,
которая настраивает связи между моделями -
значение
lazy='select',
которое загружает связи отдельным запросом -
значение
lazyload,
которое откладывает загрузку до первого обращения -
значение
lazy='raise',
которое выбрасывает исключение при обращении к связи