处理同一实体的多个实例和状态

时间:2012-08-20 12:39:06

标签: python sqlalchemy

from sqlalchemy.orm import Session
s = Session()
s.autoflush = False
s.autocommit = False

p1 = s.query(Person).first()
print p1 #prints 'Ivan Petrov', correct name of a person #1
p1.name = 'John Smith' #change the person's name

p2 = s.query(Person).first()
print p2 #prints 'John Smith', but the object wasn't flushed yet.

所以,问题是 - 我如何正确处理这种情况?我需要更改p1,不要影响会话(和p2),直到我这样说。

2 个答案:

答案 0 :(得分:2)

您可以尝试从会话中分离对象:

session.expunge(p1)

要重新连接,您可以尝试:

p2 = session.merge(p1)

或使用不同的会话对象。但迟早会出现你操纵同一个实体的事实。

答案 1 :(得分:0)

在SQLALchemy中投入了大量的工作,使其以正确的方式工作 - 而不是现在就需要它。

在不了解SQLAlchemy内部的情况下,我可以想到这样做的一种方法是使用您正在更改的实例创建一个代理对象,并在那里进行所有更改以仅在被告知时更改原始对象。

class AlchemyProxy(object):
    def __init__(self, obj):
        self._obj = obj
        self._changes = []

    def __setattr__(self, attr, value):
        self._changes.append((attr, value)
        # change the attributes in this instance
        return object.__setattr__(self, attr, value)

    def __getattr__(self, attr):
        # This is only called when the requested attribute was not
        return getattr(self._obj, attr)

    def _commit(self):
        for attr, value in self._changes:
            setattr(self._obj, attr, value)

并使用它:

p1 = AlchemyProxy(s.query(Person).first())