SQLAlChemy-Session.query循环中的Session.Commit重置对象__dict__

2022-02-22 00:00:00 python sqlalchemy

问题描述

迭代session.Query对象并调用update时,我注意到返回的对象不再填充其__dict__

例如

foos = session.query(Foo)
for foo in foos:
    print "{}".format(foo.__dict__)
    foo.somefield = "somevalue"
    session.add(foo)
    session.commit()  # The next print statement won't show anything

如果在迭代期间读取了foo中的任何字段,则将解析所有__dict__字段。

例如

foos = session.query(Foo)
for foo in foos:
    # Reading any of the fields, causes all of the fields to be resolved.
    foo.somefield
    print "{}".format(foo.__dict__)
    foo.somefield = "somevalue"
    session.add(foo)
    session.commit()  # The next print statement won't show anything

是否有方法使这些值显示在__dict__中,而无需先读取它们?


解决方案

发生这种情况的原因是在您调用commit()之后,SQLAlChemy会自动使您的实例过期。那么按顺序发生什么:

  1. 您加载所有Foo
  2. 打印__dict__,作品
  3. 提交
  4. 所有Foo均已过期(清空所有Foo中的__dict__)
  5. 打印__dict__,空,Oops

读取字段将延迟地从数据库重新加载实例,这就是这种方式工作的原因。您要做的是关闭expire_on_commit,例如,如果您使用sessionmaker

Session = sessionmaker(expire_on_commit=False)

但请注意,朴素的代码可能不再执行您预期的操作。

相关文章