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

Функция selectin_polymorphic

Функция selectin_polymorphic применяется для загрузки иерархии наследования моделей. Она принимает базовый класс и список подклассов. При обращении к полиморфным атрибутам SQLAlchemy выполняет дополнительный запрос с SELECT IN вместо отдельного запроса для каждого подкласса.

Функция полезна при работе с наследованием, когда требуется загрузить объекты разных типов одной иерархии без использования joined-загрузки. Она передается в параметр options метода query или функции select.

Синтаксис

from sqlalchemy.orm import selectin_polymorphic selectin_polymorphic(base_class, [subclass1, subclass2])

Пример

Давайте создадим иерархию моделей с наследованием и загрузим полиморфные объекты:

from sqlalchemy import create_engine, ForeignKey, String, Integer from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session from sqlalchemy.orm import selectin_polymorphic class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] = mapped_column(String(100)) status: Mapped[str] = mapped_column(String(50)) type: Mapped[str] = mapped_column(String(50)) __mapper_args__ = { 'polymorphic_on': type, 'polymorphic_identity': 'article' } class PublishedArticle(Article): __mapper_args__ = { 'polymorphic_identity': 'published' } num: Mapped[int] = mapped_column(Integer, nullable=True) class DraftArticle(Article): __mapper_args__ = { 'polymorphic_identity': 'draft' } text: Mapped[str] = mapped_column(String(500), nullable=True) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ PublishedArticle(title='article 1', status='active', num=1), DraftArticle(title='article 2', status='new', text='draft text'), PublishedArticle(title='article 3', status='active', num=3) ]) session.commit() res = session.query(Article).options( selectin_polymorphic(Article, [PublishedArticle, DraftArticle]) ).all() for article in res: print(type(article).__name__, article.title)

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

PublishedArticle article 1 DraftArticle article 2 PublishedArticle article 3

Пример

Давайте сравним количество запросов при использовании selectin_polymorphic и без него:

from sqlalchemy import create_engine, String, Integer, event from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session from sqlalchemy.orm import selectin_polymorphic class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] = mapped_column(String(100)) type: Mapped[str] = mapped_column(String(50)) __mapper_args__ = { 'polymorphic_on': type, 'polymorphic_identity': 'article' } class PublishedArticle(Article): __mapper_args__ = { 'polymorphic_identity': 'published' } num: Mapped[int] = mapped_column(Integer, nullable=True) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) query_count = 0 @event.listens_for(engine, 'before_cursor_execute') def count_queries(conn, cursor, statement, parameters, context, executemany): global query_count query_count += 1 with Session(engine) as session: session.add(PublishedArticle(title='article 1', num=1)) session.commit() query_count = 0 res = session.query(Article).options( selectin_polymorphic(Article, [PublishedArticle]) ).all() print('Queries with selectin_polymorphic:', query_count)

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

"Queries with selectin_polymorphic: 2"

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

  • функцию selectinload,
    которая загружает связи через SELECT IN
  • функцию joinedload,
    которая загружает связи через JOIN
  • функцию subqueryload,
    которая загружает связи через подзапрос
  • функцию contains_eager,
    которая указывает на уже загруженные связи
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить