Я хочу получить вычисленное поле при возврате после обновления (sqlalchemy)Python

Программы на Python
Ответить
Anonymous
 Я хочу получить вычисленное поле при возврате после обновления (sqlalchemy)

Сообщение Anonymous »

Простой пример:
from sqlalchemy import Column, Integer, Computed, update, insert, select
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import DeclarativeBase, declared_attr

engine = create_async_engine(url="postgresql+asyncpg://db_user:db_pass@localhost:54320/db_name")
async_session = async_sessionmaker(bind=engine)

class BaseTable(DeclarativeBase):
@declared_attr
def __tablename__(cls) -> str:
return cls.__name__.lower()

class Tablichka(BaseTable):
id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
quantity = Column(Integer, nullable=False)
price = Column(Integer, nullable=False)
total_cost = Column(Integer, Computed("quantity * price")) # Attention!

Я хочу обновить строку с помощью запроса orm. Мне нужно получить результат, поэтому я использую return:
async def run():
async with async_session() as session:
statement = insert(Tablichka).values(quantity=2, price=100).returning(Tablichka)
obj = (await session.execute(statement)).scalar_one()
print(f"total_cost: wait 200, really {obj.total_cost}") # total_cost: wait 200, really 200
id = obj.id

statement = update(Tablichka).filter_by(id=id).values(quantity=4, price=100).returning(Tablichka)
obj = (await session.execute(statement)).scalar_one()
print(f"total_cost: wait 400, really {obj.total_cost}") # total_cost: wait 400, really 200

statement = select(Tablichka).filter_by(id=id)
obj = (await session.execute(statement)).scalar_one()
print(f"total_cost: wait 400, really {obj.total_cost}") # total_cost: wait 400, really 200

await session.commit()

async with async_session() as session:
statement = select(Tablichka).filter_by(id=id)
obj = (await session.execute(statement)).scalar_one()
print(f"\ntotal_cost: wait 400, really {obj.total_cost}") # total_cost: wait 400, really 400

if __name__ == "__main__":
import asyncio

loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()

После обновления я ожидаю получить пересчитанную сумму total_cost, но получаю старую сумму total_cost. Я получаю обновленные поля, кроме вычисляемых полей. При этом значение пересчитывается в базе данных. Это подтверждает запрос выбора в новом сеансе.
Как мне решить проблему?
На самом деле, у меня есть рабочий пример. Но я не понимаю, почему это работает:
async def run_create(session: AsyncSession):
statement = insert(Tablichka).values(quantity=2, price=100).returning(Tablichka)
obj = (await session.execute(statement)).scalar_one()
print(f"total_cost: wait 200, really {obj.total_cost}") # total_cost: wait 200, really 200
return obj.id

async def run_update(session: AsyncSession, id: int):
statement = update(Tablichka).filter_by(id=id).values(quantity=4, price=100).returning(Tablichka)
obj = (await session.execute(statement)).scalar_one()
print(f"total_cost: wait 400, really {obj.total_cost}") # total_cost: wait 400, really 400

async def run():
async with async_session() as session:
id = await run_create(session)
await run_update(session, id)

if __name__ == "__main__":
import asyncio

loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()

Но в моем проекте есть более сложный пример, в котором я не могу использовать свой рабочий пример. Мне нужно исправить мой сломанный пример.
Я использую следующие версии:
python = "^3.10"
sqlalchemy = "^2.0.35"
asyncpg = "^0.29.0"
greenlet = "^3.1.0"


Подробнее здесь: https://stackoverflow.com/questions/790 ... sqlalchemy
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»