Функция with_expression
Функция with_expression позволяет добавить в ORM-запрос произвольное SQL-выражение и сохранить вычисленный результат в заданном атрибуте загружаемого объекта. Первым параметром передается атрибут, в который будет записан результат, вторым - SQL-выражение. Функция полезна, когда нужно получить вычисляемое значение вместе с объектами модели, например агрегат или подзапрос, без изменения самой таблицы.
Синтаксис
with_expression(attribute, expression)
Пример
Давайте создадим модель Article и добавим в запрос вычисляемое выражение, которое вернет длину заголовка. Результат сохраним во временном атрибуте title_length:
from sqlalchemy import create_engine, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
from sqlalchemy.orm import with_expression
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]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article', text='text', status='new', num=1))
session.commit()
res = session.query(Article).options(
with_expression(Article.title_length, func.length(Article.title))
).first()
print(res.title_length)
Результат выполнения кода:
7
Пример
Давайте используем with_expression вместе с агрегатной функцией для получения количества статей в том же запросе:
from sqlalchemy import create_engine, func, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
from sqlalchemy.orm import with_expression
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]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add_all([
Article(title='article 1', text='text', status='new', num=1),
Article(title='article 2', text='text', status='new', num=2),
])
session.commit()
total = select(func.count(Article.id)).scalar_subquery()
res = session.query(Article).options(
with_expression(Article.total_count, total)
).first()
print(res.total_count)
Результат выполнения кода:
2
Смотрите также
-
функцию
column_property,
которая добавляет вычисляемый атрибут в модель -
функцию
with_loader_criteria,
которая добавляет критерии загрузки в запрос -
функцию
contains_eager,
которая использует уже загруженные связи -
функцию
defer,
которая откладывает загрузку колонок