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

Значение lazy dynamic

Значение lazy="dynamic" указывается в атрибуте relationship и меняет поведение загрузки связанных объектов. Вместо списка при обращении к атрибуту возвращается объект Query, который можно донастраивать: фильтровать, сортировать и ограничивать количество записей. Это удобно для коллекций с большим числом связанных строк, когда не нужно загружать их все сразу.

Параметр lazy принимает строковое значение "dynamic". При этом сам атрибут перестаёт вести себя как обычный список: к нему нельзя применить индексацию или срез напрямую, но можно вызвать методы filter, order_by, limit и другие. Итоговая выборка выполняется только в момент итерации или вызова методов вроде all и count.

Синтаксис

relationship(..., lazy="dynamic")

Пример

Давайте опишем модель статьи и связь с комментариями через lazy="dynamic":

from sqlalchemy import create_engine, ForeignKey, String, Text from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session 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] comments: Mapped[list['Comment']] = relationship( back_populates='article', lazy='dynamic', ) class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] = mapped_column(Text) article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: article = Article( title='article', text='article text', status='published', num=1, ) article.comments = [ Comment(text='first'), Comment(text='second'), ] session.add(article) session.commit() print(type(article.comments))

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

<class 'sqlalchemy.orm.dynamic.AppenderQuery'>

Пример

Давайте применим фильтрацию к динамической связи и получим только нужные комментарии:

from sqlalchemy import create_engine, ForeignKey, String, Text from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session 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] comments: Mapped[list['Comment']] = relationship( back_populates='article', lazy='dynamic', ) class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] = mapped_column(Text) article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: article = Article( title='article', text='article text', status='published', num=1, ) article.comments = [ Comment(text='first'), Comment(text='second'), Comment(text='third'), ] session.add(article) session.commit() res = article.comments.filter(Comment.text != 'second').all() print([comment.text for comment in res])

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

['first', 'third']

Пример

Давайте посчитаем количество связанных комментариев без их полной загрузки:

from sqlalchemy import create_engine, ForeignKey, String, Text from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session 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] comments: Mapped[list['Comment']] = relationship( back_populates='article', lazy='dynamic', ) class Comment(Base): __tablename__ = 'comments' id: Mapped[int] = mapped_column(primary_key=True) text: Mapped[str] = mapped_column(Text) article_id: Mapped[int] = mapped_column(ForeignKey('articles.id')) article: Mapped['Article'] = relationship(back_populates='comments') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: article = Article( title='article', text='article text', status='published', num=1, ) article.comments = [ Comment(text='first'), Comment(text='second'), ] session.add(article) session.commit() print(article.comments.count())

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

2

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

  • атрибут relationship,
    который настраивает связи между моделями
  • значение lazy="select",
    которое загружает связь отдельным запросом
  • значение lazy="joined",
    которое загружает связь через JOIN
  • значение lazy="selectin",
    которое загружает связь пакетом через IN
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить