РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
530 of 711 menu

Значение lazy raise

Значение lazy='raise' указывается в параметре lazy функции relationship и включает режим, при котором любое обращение к связи, не загруженной заранее, приводит к исключению sqlalchemy.exc.InvalidRequestError. Параметр lazy принимает строковое значение 'raise'. Такой режим помогает отловить места, где код случайно обращается к связи и порождает лишние SQL-запросы N+1.

Синтаксис

relationship(..., lazy='raise')

Пример

Давайте создадим две модели со связью в режиме raise и попробуем обратиться к незагруженному атрибуту:

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='raise') 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') session.add(user) session.commit() with Session(engine) as session: user = session.get(User, 1) try: print(user.articles) except Exception as e: print(type(e).__name__)

Результат выполнения кода:

"InvalidRequestError"

Пример

Давайте заранее загрузим связь через selectinload и убедимся, что обращение проходит без ошибки:

from sqlalchemy import create_engine, ForeignKey, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session, selectinload 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='raise') 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') user.articles.append(Article(title='article')) session.add(user) session.commit() with Session(engine) as session: stmt = select(User).options(selectinload(User.articles)) user = session.scalars(stmt).one() print([a.title for a in user.articles])

Результат выполнения кода:

['article']

Пример

Давайте отключим режим raise на уровне запроса через raiseload с параметром False:

from sqlalchemy import create_engine, ForeignKey, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session, 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(lazy='raise') 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') user.articles.append(Article(title='article')) session.add(user) session.commit() with Session(engine) as session: stmt = select(User).options(raiseload(User.articles, False)) user = session.scalars(stmt).one() print([a.title for a in user.articles])

Результат выполнения кода:

['article']

Смотрите также

  • функцию relationship,
    которая создает связь между моделями
  • значение lazyload,
    которое включает обычную отложенную загрузку
  • значение raiseload,
    которое управляет ошибкой при загрузке связи
  • значение noload,
    которое оставляет связь пустой без запроса
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить