Anonymous
Я использую sqlalchemy и хочу получить новые значения вычисляемого поля при возврате после обновления.
Сообщение
Anonymous » 05 ноя 2024, 14:33
Простой пример:
Код: Выделить всё
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:
# Inserting
statement = insert(Tablichka).values(quantity=2, price=100).returning(Tablichka)
obj = (await session.execute(statement)).scalar_one()
# total_cost: wait 200, really 200
print(f"total_cost: wait 200, really {obj.total_cost}")
id = obj.id
# Updating
statement = update(Tablichka).filter_by(id=id).values(quantity=4, price=100).returning(Tablichka)
obj = (await session.execute(statement)).scalar_one()
# total_cost: wait 400, really 200
print(f"total_cost: wait 400, really {obj.total_cost}")
# Selecting
statement = select(Tablichka).filter_by(id=id)
obj = (await session.execute(statement)).scalar_one()
# total_cost: wait 400, really 200
print(f"total_cost: wait 400, really {obj.total_cost}")
await session.commit()
async with async_session() as session:
# Selecting in another session
statement = select(Tablichka).filter_by(id=id)
obj = (await session.execute(statement)).scalar_one()
# total_cost: wait 400, really 400
print(f"\ntotal_cost: wait 400, really {obj.total_cost}")
if __name__ == "__main__":
import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()
После обновления я ожидаю получить пересчитанную сумму total_cost, но получаю старую сумму total_cost. Я получаю обновленные поля, кроме вычисляемых полей. При этом значение пересчитывается в базе данных. Это подтверждает запрос выбора в новом сеансе.
Я использую следующие версии:
Код: Выделить всё
python = "^3.10"
sqlalchemy = "^2.0.35"
asyncpg = "^0.29.0"
greenlet = "^3.1.0"
Как решить проблему?
Подробнее здесь:
https://stackoverflow.com/questions/790 ... ning-after
1730806403
Anonymous
Простой пример: [code]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! [/code] Я хочу обновить строку с помощью запроса orm. Мне нужно получить результат, поэтому я использую return: [code]async def run(): async with async_session() as session: # Inserting statement = insert(Tablichka).values(quantity=2, price=100).returning(Tablichka) obj = (await session.execute(statement)).scalar_one() # total_cost: wait 200, really 200 print(f"total_cost: wait 200, really {obj.total_cost}") id = obj.id # Updating statement = update(Tablichka).filter_by(id=id).values(quantity=4, price=100).returning(Tablichka) obj = (await session.execute(statement)).scalar_one() # total_cost: wait 400, really 200 print(f"total_cost: wait 400, really {obj.total_cost}") # Selecting statement = select(Tablichka).filter_by(id=id) obj = (await session.execute(statement)).scalar_one() # total_cost: wait 400, really 200 print(f"total_cost: wait 400, really {obj.total_cost}") await session.commit() async with async_session() as session: # Selecting in another session statement = select(Tablichka).filter_by(id=id) obj = (await session.execute(statement)).scalar_one() # total_cost: wait 400, really 400 print(f"\ntotal_cost: wait 400, really {obj.total_cost}") if __name__ == "__main__": import asyncio loop = asyncio.get_event_loop() loop.run_until_complete(run()) loop.close() [/code] После обновления я ожидаю получить пересчитанную сумму total_cost, но получаю старую сумму total_cost. Я получаю обновленные поля, кроме вычисляемых полей. При этом значение пересчитывается в базе данных. Это подтверждает запрос выбора в новом сеансе. Я использую следующие версии: [code]python = "^3.10" sqlalchemy = "^2.0.35" asyncpg = "^0.29.0" greenlet = "^3.1.0" [/code] Как решить проблему? Подробнее здесь: [url]https://stackoverflow.com/questions/79011816/i-use-sqlalchemy-and-want-to-get-new-values-of-computed-field-in-returning-after[/url]