Функция with_loader_criteria
Функция with_loader_criteria добавляет
дополнительное условие фильтрации к сущностям,
которые загружаются через связь. Первым параметром
функция принимает класс сущности, к которой нужно
применить критерий. Вторым параметром передается
SQL-выражение с условием. Третий необязательный
параметр include_aliases управляет
применением критерия к алиасам сущности.
Функция применяется внутри опций загрузки,
таких как selectinload, joinedload
или subqueryload, и позволяет отфильтровать
загружаемые связанные объекты без изменения
основного запроса.
Синтаксис
with_loader_criteria(entity, criterion, [include_aliases])
Пример
Давайте создадим две связанные модели и
загрузим только активные статьи пользователя.
Для этого используем with_loader_criteria
вместе с selectinload:
from sqlalchemy import create_engine, ForeignKey, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
from sqlalchemy.orm import selectinload, with_loader_criteria
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
articles: Mapped[list['Article']] = relationship(back_populates='user')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
status: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(id=1, title='user')
user.articles = [
Article(id=1, title='article 1', status='active'),
Article(id=2, title='article 2', status='draft'),
Article(id=3, title='article 3', status='active'),
]
session.add(user)
session.commit()
stmt = (
select(User)
.options(
selectinload(User.articles).options(
with_loader_criteria(Article, Article.status == 'active')
)
)
)
res = session.scalars(stmt).unique().all()
for u in res:
print([a.title for a in u.articles])
Результат выполнения кода:
Пример
Давайте применим критерий к самому классу
Article через параметр with_loader_criteria
на уровне всего запроса. В этом случае условие
затронет все загрузки этой сущности:
Результат выполнения кода:
Пример
Давайте используем with_loader_criteria
вместе с joinedload и лямбда-выражением
для критерия. Лямбда позволяет сослаться на
класс сущности без явного импорта:
Результат выполнения кода:
Смотрите также
-
функцию
selectinload,
которая загружает связи отдельным запросом -
функцию
joinedload,
которая загружает связи через JOIN -
функцию
subqueryload,
которая загружает связи через подзапрос -
функцию
with_expression,
которая добавляет SQL-выражение к загружаемому объекту