gpt4 book ai didi

python - sqlalchemy 对象如何分离?

转载 作者:太空狗 更新时间:2023-10-30 00:07:26 25 4
gpt4 key购买 nike

我的代码结构如下:

project
--app
----utils
------util.py
----__init__.py
----models.py
--tests
----__init__.py

在 tests/__init__.py 中,我有代码通过从 app/__init__.py 中导入来初始化应用程序(如果重要的话是 flask)和数据库 session 。我可以在 tests/__init__.py 中创建模型、查询和访问反向引用的实例。以下形式的代码工作正常:

objs = SomeModel.query.all()
for o in objs:
o.backref

但是,如果我这样做:

from utils.util import some_function
objs = SomeModel.query.all()
for o in objs:
some_function(o)

其中 some_function 只是访问一个 backref

def some_function(obj):
obj.backref

我收到类似 DetachedInstanceError: Parent instance <SomeModel at 0x2c1fe10> is not bound to a Session; lazy load operation of attribute 'backref' cannot proceed 的错误

阅读 sqlalchemy 文档表明我需要将对象重新关联到数据库 session 。我这样做了,它看起来很有效(即运行该函数不会因先前的错误而失败):

import db_session
def some_function(obj):
db_session.add(obj)
obj.backref

那么一个对象究竟是什么时候分离的呢?似乎只是将对象传递给另一个模块中的函数会将其从 session 中分离出来。对象是否不知道与其关联的 sqlalchemy session ?我试图避免做 db_session.add(obj)这看起来像是很多样板代码。

最佳答案

我在自己工作时遇到了这个 similar question关于属性过期和实例分离。 univerio给了我一个很好的答案,并且根据我一直在学习的知识,我也许能够阐明您的问题。

在我的例子中,我创建、提交或回滚,然后关闭一个 Session,所有这些都在单个 with...as... 子句的范围内,然后立即尝试访问我保存的实例(在您的示例中为 obj)但在该 with 子句 的范围之外。发生的事情是 Session 在我尝试引用保存的对象之前关闭了。 默认情况下,在 SQLAlchemy 中,如果没有active Session,则无法访问持久属性/对象,除非明确告知允许它。这是为了“保护”代码免于意外或不知不觉地使用过时/不正确的数据,方法是强制应用程序首先查询/检索更新的数据,这需要关联的Session。所以在我的例子中,在提交后保持 Session 打开意味着对象可以使用 Session 来查询数据库,以防记录在第一次写入后被修改。

在您的情况下,用于通过 objs = SomeModel.query.all() 获取对象的 Session 在查询之后但在 obj.backref 被调用(虽然我不确定如何;我不知道 SomeModel 是什么,确切地说,我假设是 Flask 的一个构造,它包含一个Session 在其后台)。所以 obj 不再与数据库有连接,因此是“分离的”。通过将它添加到 db_session,您允许 obj 重新建立与其源数据库的连接,通过它可以查询以检查更新的属性,因此它不再分离。

最后,值得一提的是,DetachedInstanceError 可以通过指定 obj 关联的原始 Session 而不是 来避免自动过期属性。如果 expiring obj,则不会抛出错误,obj 仍会分离,这意味着当您调用 obj.backref 时,返回的值可能不正确/已过时。您在问题中询问了分离,但过期是一个相关但不完全相同的概念。

旁白 -- 如何设置 obj 不会过期:Session 的初始化时

my_session = sessionmaker(expire_on_commit=False

sessionmaker 的初始化

my_sessionmaker = sqlalchemy.orm.sessionmaker(expire_on_commit=False)

甚至在 Session 已经实例化之后

my_session.expire_on_commit = False

关于python - sqlalchemy 对象如何分离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19818082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com