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

标签 python mysql orm sqlalchemy

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

这部分与之前关于 bulk update strategies 的问题有关.

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

我尝试了下面的策略,但它导致对象从 session 中删除,这可能会在以后发生延迟加载时导致问题。

@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

关于python - 在 SQLAlchemy ORM 中将对象标记为干净,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41879671/

相关文章:

python - 在 Python 中弹出图形对话框的最简单的跨平台方法是什么?

mysql - 如何成功添加触发器

mysql - ubuntu 服务器 10.4 中缺少/tmp/mysql.socket 文件

MySQL:使用计数来限制结果?

python - Django QuerySet .defer() 问题 - 错误或功能?

python - 破坏 {% load range_template_tags %} 上的模板

python - 使用 xarray 添加和使用附加坐标

python - 如何使用 Python 函数显示不同的错误消息

grails - 如何更改 Grails 域类 ID 字段的名称?

django - Django ORM和锁定表