迭代SQLAlchemy查询就是重新设置新分配的变量



我一直在使用SQLAlchemy连接到MySQL数据库。到目前为止,它一直运行良好,但我遇到了一些麻烦。我想在我的一个类被查询后调用一个方法,该方法将分配一些新变量。问题是,每个查询只有一个用户最终拥有由我的"on_query"方法设置的变量。

...stuff setting up a connection to the database as well as a SQL session.
   All were done using default values.
class UserTest(Base):
    __tablename__ = "testtable"
    ID = Column(Integer(unsigned=True),
                primary_key=True, nullable=False, autoincrement=True)
    def __init__(self):
        pass
    def on_query(self):
        self.foo = "bar"
query = session.query(UserTest)
for u in query:
    u.on_query()
print [hasattr(u, "foo") for u in query]
#prints [False, False, False, False, False, False, False, False, False, True]
session.close()

我发现,如果我要通过迭代查询来创建一个列表,"on_query"方法将按我的预期工作

users = [u for u in query]
for u in users:
    u.on_query()
print [hasattr(u, "foo") for u in users]
#prints [True, True, True, True, True, True, True, True, True, True]

这是什么原因造成的?有没有办法阻止它在每次迭代中删除"foo"变量?如果可能的话,我更愿意将Users保留在查询对象中。

在第一种情况下,查询实际上派生了两次,一次是由for循环派生的,一次由print语句派生的。

由于for循环不断替换u引用,因此在循环结束时,SQLAlchemy会话中只剩下最后一个引用。您可以使用print session.identity_map对此进行验证。

当print语句第二次派生查询时,除最后一个查询外,所有查询都必须再次从数据库中检索,而最后一个则直接从SQLAlchemy会话中检索,因此设置了foo属性。

编辑:一种更透明的方法是使用重建器,例如

class UserTest(Base):
    ...
    @orm.reconstructor
    def init_on_load(self):
        self.foo = "bar"

最新更新