To, co zasadniczo robisz, to omijanie ORM w celu zoptymalizowania wydajności. Dlatego nie zdziw się, że „replikujesz pracę wykonywaną przez ORM”, ponieważ to jest dokładnie to, co musisz zrobić.
O ile nie masz wielu miejsc, w których musisz robić masowe aktualizacje, takie jak ta, odradzałbym podejście do magicznych wydarzeń; po prostu pisanie wyraźnych zapytań jest znacznie prostsze.
Zalecam użycie SQLAlchemy Core zamiast ORM do przeprowadzenia aktualizacji:
ledger = Table("ledger", db.metadata,
Column("wallet_id", Integer, primary_key=True),
Column("new_balance", Float),
prefixes=["TEMPORARY"],
)
wallets = db_session.query(Wallet).all()
# figure out new balances
balance_map = {}
for w in wallets:
balance_map[w.id] = calculate_new_balance(w)
# create temp table with balances we need to update
ledger.create(bind=db.session.get_bind())
# insert update data
db.session.execute(ledger.insert().values([{"wallet_id": k, "new_balance": v}
for k, v in balance_map.items()])
# perform update
db.session.execute(Wallet.__table__
.update()
.values(balance=ledger.c.new_balance)
.where(Wallet.__table__.c.id == ledger.c.wallet_id))
# drop temp table
ledger.drop(bind=db.session.get_bind())
# commit changes
db.session.commit()