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

Функция with_polymorphic

Функция with_polymorphic создает специальный селектор, который позволяет загружать объекты иерархии наследуемых классов в одном запросе. Первым параметром функция принимает базовый класс иерархии. Вторым параметром передается список наследуемых классов, которые нужно загрузить одним запросом. Если вместо списка указать строку '*', то будут загружены все классы иерархии.

Обычно функция with_polymorphic используется вместе с методом select. Она помогает избежать проблемы N+1, когда для каждого объекта иерархии выполняется отдельный запрос к таблице наследника.

Синтаксис

with_polymorphic(base_class, [classes]) with_polymorphic(base_class, '*')

Пример

Давайте создадим иерархию классов, где Article является базовым классом, а TextArticle и NumArticle - наследниками:

from sqlalchemy import create_engine, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.orm import with_polymorphic, Session class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] status: Mapped[str] type: Mapped[str] __mapper_args__ = { 'polymorphic_identity': 'article', 'polymorphic_on': type } class TextArticle(Article): text: Mapped[str] __mapper_args__ = { 'polymorphic_identity': 'text_article' } class NumArticle(Article): num: Mapped[int] __mapper_args__ = { 'polymorphic_identity': 'num_article' } engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine)

Пример

Теперь загрузим все объекты иерархии одним запросом с помощью функции with_polymorphic:

<+python+> from sqlalchemy import create_engine, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.orm import with_polymorphic, Session class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] type: Mapped[str] __mapper_args__ = { 'polymorphic_identity': 'article', 'polymorphic_on': type } class TextArticle(Article): text: Mapped[str] __mapper_args__ = { 'polymorphic_identity': 'text_article' } class NumArticle(Article): num: Mapped[int] __mapper_args__ = { 'polymorphic_identity': 'num_article' } engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add(TextArticle(title='article 1', text='some text')) session.add(NumArticle(title='article 2', num=42)) session.commit() poly = with_polymorphic(Article, [TextArticle, NumArticle]) stmt = select(poly) res = session.scalars(stmt).all() for obj in res: print(type(obj).__name__, obj.title) <-python+>

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

"TextArticle article 1" "NumArticle article 2"

Пример

Если вместо списка классов передать строку '*', то будут загружены все классы иерархии:

<+python+> from sqlalchemy import create_engine, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.orm import with_polymorphic, Session class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] type: Mapped[str] __mapper_args__ = { 'polymorphic_identity': 'article', 'polymorphic_on': type } class TextArticle(Article): text: Mapped[str] __mapper_args__ = { 'polymorphic_identity': 'text_article' } class NumArticle(Article): num: Mapped[int] __mapper_args__ = { 'polymorphic_identity': 'num_article' } engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add(TextArticle(title='article 1', text='some text')) session.add(NumArticle(title='article 2', num=42)) session.commit() poly = with_polymorphic(Article, '*') stmt = select(poly) res = session.scalars(stmt).all() for obj in res: print(type(obj).__name__, obj.title) <-python+>

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

<+python+> "TextArticle article 1" "NumArticle article 2" <-python+>

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

  • функцию select,
    которая создает SELECT-запрос
  • функцию aliased,
    которая создает псевдоним для класса
  • функцию values,
    которая создает конструкцию VALUES
  • функцию union,
    которая объединяет результаты запросов
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить