Функция raiseload
Функция raiseload запрещает ленивую загрузку
связанных объектов. Она применяется в опциях загрузки
запроса и заставляет SQLAlchemy выбрасывать исключение
InvalidRequestError, если код попытается обратиться
к отношению, которое не было загружено заранее. Первым
параметром функция принимает атрибут отношения или
строку с именем отношения. Вторым необязательным
параметром передается флаг sql_only, который
ограничивает проверку только SQL-запросами.
Синтаксис
raiseload(attr, [sql_only])
Пример
Давайте создадим две связанные модели и попробуем обратиться к отношению, для которого запрещена ленивая загрузка:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
from sqlalchemy.orm import raiseload
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]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(title='article', user=user)
session.add_all([user, article])
session.commit()
res = session.query(User).options(raiseload(User.articles)).first()
print(res.name)
try:
print(res.articles)
except Exception as e:
print(type(e).__name__)
Результат выполнения кода:
"user"
"InvalidRequestError"
Пример
Давайте запретим ленивую загрузку через строковое имя отношения:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
from sqlalchemy.orm import raiseload
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]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(title='article', user=user)
session.add_all([user, article])
session.commit()
res = session.query(User).options(raiseload('articles')).first()
print(res.name)
try:
print(res.articles)
except Exception as e:
print(type(e).__name__)
Результат выполнения кода:
"user"
"InvalidRequestError"
Пример
Давайте используем параметр sql_only, чтобы
запретить только SQL-загрузку, но разрешить
загрузку из уже загруженных объектов:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
from sqlalchemy.orm import raiseload, joinedload
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]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(title='article', user=user)
session.add_all([user, article])
session.commit()
res = session.query(User).options(joinedload(User.articles), raiseload(User.articles, sql_only=True)).first()
print(res.name)
print([a.title for a in res.articles])
Результат выполнения кода:
"user"
['article']
Смотрите также
-
функцию
joinedload,
которая загружает отношение через JOIN -
функцию
selectinload,
которая загружает отношение отдельным SELECT -
функцию
lazyload,
которая включает ленивую загрузку отношения -
функцию
noload,
которая отключает загрузку отношения