在SQLAlchemy ORM中将对象标记为干净

2024-09-29 21:57:56 发布

您现在位置:Python中文网/ 问答频道 /正文

在SQLAlchemy ORM中,有没有任何方法可以显式地将一个对象标记为clean?在

这部分与前面关于bulk update strategies的问题有关。在

我想在一个before_flush事件侦听器中,将一堆对象标记为实际上不需要刷新。这是因为它们通过其他方式手动与数据库同步。在

我已经尝试过下面的策略,但是它会导致对象从会话中被移除,这会在以后发生延迟加载时引发问题。在

@event.listens_for(SignallingSession, 'before_flush')
def before_flush(session, flush_context, instances):
    ledgers = []

    if session.dirty:
        for elem in session.dirty:
            if ( session.is_modified(elem, include_collections=False) ):
                if isinstance(elem, Wallet):
                    session.expunge(elem) # causes problems later
                    ledgers.append(Ledger(id=elem.id, amount=elem.balance))

    if ledgers:
        session.bulk_save_objects(ledgers)
        session.execute('UPDATE wallet w JOIN ledger l on w.id = l.id SET w.balance = l.amount')
        session.execute('TRUNCATE ledger')

我想做些类似的事情:

^{pr2}$

但这并不起作用,因为session.dirty是一个计算属性,而不是常规属性。我一直在研究检测代码,但不明白如何才能使dirty列表不包含某些内容。我看到在对象状态上还有一个history也需要处理。在

有什么想法吗?如果有什么不同的话,底层数据库是MySQL。在

-马特


Tags: 对象标记id数据库forifsessionbulk
2条回答

让我总结一下这种疯狂。在

from sqlalchemy.orm import attributes

attributes.instance_state(your_object).committed_state.clear()

别紧张。(没有)

当您在ORM之外修改数据库时,可以使用^{}让ORM知道当前的数据库状态。在

示例:

wallet = session.query(Wallet).filter_by(id=123)
wallet.balance = 0
session.execute("UPDATE wallet SET balance = 0 WHERE id = 123;")
set_committed_value(wallet, "balance", 0)
session.commit()  # won't issue additional SQL to update wallet

如果真的想要将实例标记为not dirty,那么可以处理SQLAlchemy的内部结构:

^{pr2}$

相关问题 更多 >

    热门问题