Значение lazy selectin
Значение lazy selectin задает стратегию
загрузки связанных объектов, при которой
SQLAlchemy выполняет дополнительный
SELECT IN запрос для получения всех
связанных записей одним пакетом. Стратегия
указывается в параметре lazy функции
relationship при описании связи между
моделями. В отличие от ленивой загрузки,
которая обращается к базе при каждом
обращении к атрибуту, selectin
подгружает связи сразу после загрузки
родительских объектов.
Синтаксис
relationship(..., lazy='selectin')
Пример
Давайте опишем две связанные модели,
где связь использует стратегию
selectin:
from sqlalchemy import ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
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(lazy='selectin')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
Теперь при загрузке пользователей SQLAlchemy одним дополнительным запросом подтянет все связанные статьи:
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session
from models import Base, User, Article
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(id=1, title='user')
article = Article(id=1, title='article', user_id=1)
session.add_all([user, article])
session.commit()
res = session.scalars(select(User)).all()
for u in res:
print(u.title, [a.title for a in u.articles])
Результат выполнения кода:
"user ['article']"
Итоговый SQL запрос:
SELECT users.id, users.title FROM users
SELECT articles.user_id AS articles_user_id, articles.id AS articles_id, articles.title AS articles_title FROM articles WHERE articles.user_id IN (1)
Пример
Стратегию selectin можно переопределить
на уровне отдельного запроса с помощью
опции selectinload:
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session, selectinload
from models import Base, User, Article
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(id=1, title='user')
article = Article(id=1, title='article', user_id=1)
session.add_all([user, article])
session.commit()
stmt = select(User).options(selectinload(User.articles))
res = session.scalars(stmt).all()
for u in res:
print(u.title, [a.title for a in u.articles])
Результат выполнения кода:
"user ['article']"
Итоговый SQL запрос:
SELECT users.id, users.title FROM users
SELECT articles.user_id AS articles_user_id, articles.id AS articles_id, articles.title AS articles_title FROM articles WHERE articles.user_id IN (1)
Смотрите также
-
функцию
relationship,
которая описывает связь между моделями -
функцию
selectinload,
которая задает стратегию загрузки на уровне запроса -
значение
lazy select,
которое включает ленивую загрузку связей -
значение
lazy joined,
которое загружает связи через JOIN