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

Метод expression класса hybrid_property

Метод expression класса hybrid_property задает SQL-выражение, которое используется при обращении к гибридному свойству на уровне класса, то есть внутри запросов. Первым параметром метод принимает функцию, возвращающую SQL-выражение на основе колонок модели. Без этого метода гибридное свойство работает только на уровне экземпляра объекта.

Синтаксис

@hybrid_property def name(self): ... @name.expression def name(cls): ...

Пример

Давайте создадим модель Article с гибридным свойством is_published, которое проверяет статус статьи. Сначала опишем Python-версию свойства для работы с экземпляром объекта:

from sqlalchemy import create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session from sqlalchemy.ext.hybrid import hybrid_property class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] text: Mapped[str] status: Mapped[str] num: Mapped[int] @hybrid_property def is_published(self): return self.status == 'published'

Теперь добавим метод expression, чтобы то же свойство можно было использовать в фильтрах запросов:

from sqlalchemy import create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session from sqlalchemy.ext.hybrid import hybrid_property class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] text: Mapped[str] status: Mapped[str] num: Mapped[int] @hybrid_property def is_published(self): return self.status == 'published' @is_published.expression def is_published(cls): return cls.status == 'published'

Пример

Давайте проверим, как гибридное свойство работает и на уровне экземпляра, и на уровне класса в запросе. Создадим таблицу и добавим несколько статей:

from sqlalchemy import create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session from sqlalchemy.ext.hybrid import hybrid_property class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] text: Mapped[str] status: Mapped[str] num: Mapped[int] @hybrid_property def is_published(self): return self.status == 'published' @is_published.expression def is_published(cls): return cls.status == 'published' engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article 1', text='text 1', status='published', num=1), Article(title='article 2', text='text 2', status='draft', num=2), Article(title='article 3', text='text 3', status='published', num=3), ]) session.commit() article = session.get(Article, 1) print(article.is_published) res = session.query(Article).filter(Article.is_published).all() print([a.title for a in res])

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

True ['article 1', 'article 3']

Итоговый SQL запрос:

SELECT articles.id AS articles_id, articles.title AS articles_title, articles.text AS articles_text, articles.status AS articles_status, articles.num AS articles_num FROM articles WHERE articles.status = 'published'

Пример

Давайте создадим гибридное свойство full_title, которое объединяет заголовок и номер статьи, и применим его в запросе:

from sqlalchemy import create_engine, String, func from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session from sqlalchemy.ext.hybrid import hybrid_property class Base(DeclarativeBase): pass class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] text: Mapped[str] status: Mapped[str] num: Mapped[int] @hybrid_property def full_title(self): return f'{self.title} #{self.num}' @full_title.expression def full_title(cls): return cls.title + ' #' + func.cast(cls.num, String) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article', text='text 1', status='published', num=1), Article(title='article', text='text 2', status='draft', num=2), ]) session.commit() article = session.get(Article, 2) print(article.full_title) res = session.query(Article.full_title).all() print(res)

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

"article #2" [('article #1',), ('article #2',)]

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

  • класс hybrid_property,
    который создает гибридные свойства
  • метод getter,
    который задает Python-геттер для свойства
  • метод setter,
    который задает Python-сеттер для свойства
  • метод comparator,
    который настраивает сравнение свойства
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить