SQLAlchemy - Session.query 循环中的 Session.commit 重置对象 __dict__

fun*_*iki 3 python sqlalchemy

当迭代session.Query对象并调用更新时,我注意到返回的对象不再__dict__填充它们的's 。

例如

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
Run Code Online (Sandbox Code Playgroud)

但是,如果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
Run Code Online (Sandbox Code Playgroud)

有没有办法让这些值出现__dict__而无需先阅读它们?

uni*_*rio 5

发生这种情况的原因是 SQLAlchemy 在您调用commit(). 那么依次发生什么:

  1. 你加载所有Foo
  2. 打印__dict__, 作品
  3. 犯罪
  4. 所有Foos 都已过期(清空__dict__所有Foos)
  5. 打印__dict__,空,哎呀

读取一个字段会懒惰地从数据库中重新加载实例,这就是它起作用的原因。您想要做的是关闭expire_on_commit,例如,如果您使用sessionmaker

Session = sessionmaker(expire_on_commit=False)
Run Code Online (Sandbox Code Playgroud)

但请注意,原始代码可能不再按您的预期运行。

  • @funseiki 出现的问题并不是真正的边缘情况,但基本上您不能假设实例中加载的状态是最新的。您只需要记住,您可能正在处理陈旧数据,并且数据库事务语义可能无法拯救您。 (2认同)