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

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

Метод comparator класса hybrid_property позволяет задать пользовательский класс для сравнения гибридного свойства на уровне SQL. По умолчанию SQLAlchemy использует стандартный класс сравнения, который преобразует операции (например, ==, >, like) в SQL-выражения. Метод comparator принимает класс-наследник Comparator и позволяет переопределить поведение любого оператора. Это полезно, когда нужно реализовать нестандартную логику сравнения, которая не сводится к простому отображению на колонку.

Синтаксис

from sqlalchemy.ext.hybrid import hybrid_property @hybrid_property def property_name(self): return ... @property_name.comparator def property_name(cls): return CustomComparator

Пример

Давайте создадим модель Article с гибридным свойством is_published, которое возвращает True, если статус статьи равен 'published'. Определим собственный компаратор, который преобразует сравнение в SQL-условие:

from sqlalchemy import create_engine, String 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] = mapped_column(String(100)) status: Mapped[str] = mapped_column(String(50)) @hybrid_property def is_published(self): return self.status == 'published' @is_published.comparator def is_published(cls): return ArticleComparator(cls) class ArticleComparator: def __init__(self, cls): self.cls = cls def __eq__(self, other): if other: return self.cls.status == 'published' return self.cls.status != 'published' def __ne__(self, other): if other: return self.cls.status != 'published' return self.cls.status == 'published'

Теперь создадим таблицы, добавим статьи и выполним запрос с использованием нашего компаратора:

from sqlalchemy import create_engine from sqlalchemy.orm import Session from models import Base, Article engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article 1', status='published'), Article(title='article 2', status='draft'), Article(title='article 3', status='published') ]) session.commit() res = session.query(Article).filter(Article.is_published == True).all() print([article.title for article in res])

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

['article 1', 'article 3']

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

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

Пример

Давайте усложним пример: добавим гибридное свойство has_text, которое проверяет, что поле text не пустое. Компаратор будет поддерживать сравнение с True и False:

from sqlalchemy import create_engine, String, Text 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] = mapped_column(String(100)) text: Mapped[str] = mapped_column(Text, nullable=True) @hybrid_property def has_text(self): return self.text is not None and len(self.text) > 0 @has_text.comparator def has_text(cls): return HasTextComparator(cls) class HasTextComparator: def __init__(self, cls): self.cls = cls def __eq__(self, other): if other: return self.cls.text.isnot(None) & (self.cls.text != '') return self.cls.text.is_(None) | (self.cls.text == '')

Выполним запрос и выведем статьи, у которых есть текст:

from sqlalchemy import create_engine from sqlalchemy.orm import Session from models import Base, Article engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article 1', text='some text'), Article(title='article 2', text=None), Article(title='article 3', text='') ]) session.commit() res = session.query(Article).filter(Article.has_text == True).all() print([article.title for article in res])

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

['article 1']

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

SELECT articles.id AS articles_id, articles.title AS articles_title, articles.text AS articles_text FROM articles WHERE articles.text IS NOT NULL AND articles.text != ''

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

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