繁体   English   中英

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

[英]Marking an object as clean in SQLAlchemy ORM

有没有办法在 SQLAlchemy ORM 中将对象显式标记为干净

这部分与之前关于批量更新策略的问题有关。

我想在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')

我想做类似的事情:

session.dirty.remove(MyObject)

但这不起作用,因为session.dirty是计算属性,而不是常规属性。 我一直在挖掘检测代码,但看不出我如何欺骗dirty列表不包含某些内容。 我看到还有一个关于对象状态的history也需要处理。

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

-马特

在 ORM 之外修改数据库时,可以使用set_committed_value()让 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

如果您真的想将实例标记为不脏,您可以使用 SQLAlchemy 的内部结构:

state = inspect(p)
session.identity_map._modified.discard(state)
state.modified = False
print(p in session.dirty)  # False

让我总结一下这种疯狂。

from sqlalchemy.orm import attributes

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

简单。 (不)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM