当我尝试在 SQLAlchemy ORM 中的 scoped_session 上执行预构建查询时,我收到一个奇怪的错误,AttributeError: 'scoped_session' object has no attribute '_autoflush'
。 p>
我正在使用上下文管理器来生成scoped_session,
@contextmanager
def connect(my_session_factory):
session = scoped_session(my_session_factory)
try:
yield session
except Exception as exception:
session.rollback()
raise exception
finally:
session.close()
然后像这样使用它:
from sqlalchemy.orm import Query
query = Query(my_model).offset(my_offset).limit(my_limit)
with connect(my_session_factory) as session:
instances = query.with_session(session).all()
return instances
但是,这会引发上述异常。
我还注意到 session.query(my_model)
形式的查询工作得很好。
我哪里出错了?非常感谢!
最佳答案
好吧 - 我对所提出的问题没有答案,但我似乎有一个解决方法。
问题似乎与 scoped_session
对象的代理行为有关。据我了解,scoped_session()
方法采用sessionmaker
对象并使用它来创建线程本地session
对象。但是,scoped_session()
方法不会返回此线程本地 session
。相反,它返回一个 scoped_session
对象,该对象以某种方式(我不太清楚)容纳线程本地 session
。要直接访问此线程本地 session ,您可以执行 scoped_session.registry()
,或者简单地 scoped_session()
,其中 scoped_session
这里是scoped_session
对象,已由 scoped_session
方法返回。
my_scoped_session = scoped_session(my_session_factory)
my_local_session = my_scoped_session()
现在的问题是:文档似乎建议诸如 my_scoped_session.query(...).all()
和 my_local_session.query(...).all 之类的调用()
是等效的,这要归功于 scoped_session
对象的代理行为。我发现这在很大程度上是正确的,但在我最初的问题案例中并非如此。
如果您执行 my_query = Query(...)
(即构建非 session 绑定(bind)查询),然后将其附加到 scoped_session
对象(希望利用 scoped_session
代理机制,以便在 scoped_session
线程本地 session
的上下文中处理 my_query
>),通过 my_instances = my_query.with_session(my_scoped_session).all()
或类似的方式,您可以在我原来的问题中得到回溯。
我的解决方法是完全跳过 scoped_session
对象的代理机制,而是将 my_query
直接绑定(bind)到 my_local_session
。
my_query = Query(...).filter(...).sort(...)
my_instances = my_query.with_session(my_local_session).all()
这似乎可行。但是,如果有人愿意插话直接使用 scoped_session(my_session_factory)()
而不是使用 scoped_session(my_session_factory)
的危险(如果有的话?) (大多数在线教程似乎都是这样做的),那么我将不胜感激!
关于python - 将预构建的查询附加到 SQLAlchemy 中的scoped_session,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43685758/