Метод merge
Метод merge класса AsyncSession
принимает экземпляр модели и возвращает
новый экземпляр, который привязан к текущей
сессии. Если объект с таким первичным ключом
уже существует в базе данных или в карте
идентичности сессии, состояние переданного
объекта копируется в управляемый экземпляр.
Если объекта в базе нет, создается новая
запись при следующем сбросе. Первым
параметром передается объект модели, вторым
необязательным параметром load можно
указать, нужно ли подгружать состояние из
базы данных.
Синтаксис
await session.merge(instance, [load])
Пример
Давайте создадим модель и объединим отсоединенный объект с асинхронной сессией:
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
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]
Теперь объединим объект с сессией:
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
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_async_engine('sqlite+aiosqlite:///:memory:')
async def main():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async with AsyncSession(engine) as session:
article = Article(
id=1,
title='article',
text='some text',
status='draft',
num=10
)
merged = await session.merge(article)
print(merged.title)
print(merged.status)
import asyncio
asyncio.run(main())
Результат выполнения кода:
"article"
"draft"
Пример
Давайте изменим отсоединенный объект и объединим его повторно, чтобы обновить запись в базе данных:
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
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_async_engine('sqlite+aiosqlite:///:memory:')
async def main():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async with AsyncSession(engine) as session:
article = Article(
id=1,
title='article',
text='some text',
status='draft',
num=10
)
merged = await session.merge(article)
await session.commit()
merged.title = 'user'
merged.status = 'published'
await session.commit()
res = await session.get(Article, 1)
print(res.title)
print(res.status)
import asyncio
asyncio.run(main())
Результат выполнения кода:
"user"
"published"
Пример
Давайте посмотрим итоговый SQL-запрос, который выполняется при слиянии нового объекта:
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
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_async_engine('sqlite+aiosqlite:///:memory:', echo=True)
async def main():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async with AsyncSession(engine) as session:
article = Article(
id=1,
title='article',
text='some text',
status='draft',
num=10
)
merged = await session.merge(article)
await session.commit()
print(merged.id)
import asyncio
asyncio.run(main())
Итоговый SQL запрос:
SELECT articles.id, articles.title, articles.text, articles.status, articles.num
FROM articles
WHERE articles.id = ?
INSERT INTO articles (id, title, text, status, num)
VALUES (?, ?, ?, ?, ?)
Смотрите также
-
класс
AsyncSession,
который представляет асинхронную сессию -
метод
add,
который добавляет новый объект в сессию -
метод
get,
который возвращает объект по первичному ключу -
метод
commit,
который фиксирует изменения в базе данных