Значение lazy write_only
Значение write_only параметра lazy в функции relationship
указывает SQLAlchemy, что связанная коллекция
должна загружаться исключительно для операций
записи. При чтении такая коллекция возвращает
пустой список, а все добавления и удаления
элементов выполняются напрямую через
SQL-запросы без предварительной загрузки
содержимого. Это особенно полезно для
больших коллекций, где полная загрузка
объектов в память не требуется.
Параметр lazy='write_only' передаётся
в relationship и влияет на стратегию
загрузки связанных объектов. При этом
становятся доступными методы
append, remove и
clear, но обычное чтение коллекции
возвращает пустой список.
Синтаксис
relationship(SomeClass, lazy='write_only')
Пример
Давайте создадим две модели - Article
и Tag - и свяжем их через
write_only коллекцию:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
tags: Mapped[list['Tag']] = relationship(
back_populates='article',
lazy='write_only'
)
class Tag(Base):
__tablename__ = 'tags'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'))
article: Mapped['Article'] = relationship(back_populates='tags')
Теперь создадим статью и добавим в неё теги
через write_only коллекцию:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article 1')
article.tags.append(Tag(name='python'))
article.tags.append(Tag(name='sqlalchemy'))
session.add(article)
session.commit()
print(article.tags)
Результат выполнения кода:
[]
Как видно, коллекция tags возвращает
пустой список, хотя теги были добавлены и
сохранены в базе данных.
Пример
Давайте убедимся, что теги действительно записаны в базу, выполнив отдельный запрос:
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article 1')
article.tags.append(Tag(name='python'))
article.tags.append(Tag(name='sqlalchemy'))
session.add(article)
session.commit()
res = session.scalars(select(Tag).where(Tag.article_id == article.id)).all()
print([tag.name for tag in res])
Результат выполнения кода:
['python', 'sqlalchemy']
Итоговый SQL запрос:
SELECT tags.id, tags.name, tags.article_id
FROM tags
WHERE tags.article_id = ?
Смотрите также
-
функцию
relationship,
которая создаёт связь между моделями -
значение
lazy select,
которое загружает коллекцию отдельным запросом -
значение
lazy dynamic,
которое возвращает объект запроса вместо списка -
значение
lazy noload,
которое полностью отключает загрузку коллекции