尝试在SQLAlchemy ORM中的scoped_session上执行预构建查询时,我收到一个奇怪的错误AttributeError: 'scoped_session' object has no attribute '_autoflush'
。
我正在使用上下文管理器来产生一个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)
形式的查询工作正常。
我哪里错了?非常感谢!
答案 0 :(得分:3)
好的 - 我没有对提出的问题给出答案,但我似乎确实有一个解决方法。
问题似乎与scoped_session
对象的代理行为有关。据我了解,scoped_session()
方法采用sessionmaker
对象并使用它来创建线程局部session
对象。但是,scoped_session()
方法不会返回此线程本地session
。相反,它返回一个scoped_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(...)
(即构建非会话绑定查询),然后将其附加到scoped_session
对象(希望利用scoped_session
代理机制,例如在my_query
线程本地scoped_session
的上下文中处理session
,通过my_instances = my_query.with_session(my_scoped_session).all()
或类似方式,您可以在我的原始问题中获得回溯。
我的解决方法是完全跳过scoped_session
对象的代理机制,而是将my_query
直接绑定到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)
(大多数在线教程似乎都是这样)的危险(如果有的话),那么我会不胜感激!