jav*_*vex 4 python sqlalchemy zope pyramid
我编写了自己的PyramidISession 接口实现,它将会话存储在数据库中。一切都工作得很好,但不知怎的却pyramid_tm出现了问题。一旦激活它就会这样说:
DetachedInstanceError: Instance <Session at 0x38036d0> is not bound to a Session;
attribute refresh operation cannot proceed
Run Code Online (Sandbox Code Playgroud)
(这里不要混淆:这<Session ...>是模型的类名,“... to a Session”很可能指的是 SQLAlchemy 的 Session(我称之为DBSession以避免混淆)。
我查看了邮件列表,似乎每当有人遇到问题时,他们都会
transaction.commit()这两件事我都不做。然而,这里的特点是,我的会话经常被金字塔传递。首先我这样做DBSession.add(session),然后return session。之后我可以处理会话、闪现新消息等。
但是,似乎一旦请求完成,我就会收到此异常。这是完整的回溯:
Traceback (most recent call last):
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/channel.py", line 329, in service
task.service()
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/task.py", line 173, in service
self.execute()
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/task.py", line 380, in execute
app_iter = self.channel.server.application(env, start_response)
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/pyramid/router.py", line 251, in __call__
response = self.invoke_subrequest(request, use_tweens=True)
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/pyramid/router.py", line 231, in invoke_subrequest
request._process_response_callbacks(response)
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/pyramid/request.py", line 243, in _process_response_callbacks
callback(self, response)
File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/miniblog/miniblog/models.py", line 218, in _set_cookie
print("Setting cookie %s with value %s for session with id %s" % (self._cookie_name, self._cookie, self.id))
File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 168, in __get__
return self.impl.get(instance_state(instance),dict_)
File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 451, in get
value = callable_(passive)
File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/state.py", line 285, in __call__
self.manager.deferred_scalar_loader(self, toload)
File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/mapper.py", line 1668, in _load_scalar_attributes
(state_str(state)))
DetachedInstanceError: Instance <Session at 0x7f4a1c04e710> is not bound to a Session; attribute refresh operation cannot proceed
Run Code Online (Sandbox Code Playgroud)
对于这种情况,我禁用了调试工具栏。一旦我激活它,错误就会从那里抛出。看来这里的问题是在任何时候访问该对象。
我意识到我可以尝试以某种方式分离它,但这似乎不是正确的方法,因为如果不再次将其显式添加到会话中,则无法修改该元素。
因此,当我不生成新线程并且不显式调用提交时,我猜事务是在请求完全消失之前提交的,之后又可以再次访问它。我该如何处理这个问题?
我相信您在这里看到的是一个奇怪的事实,即响应回调和完成的回调实际上是在补间之后执行的。它们位于应用程序的出口和中间件之间。pyramid_tm作为补间,在响应回调执行之前提交事务 - 导致稍后访问时出现错误。
让这些事情的顺序正确是很困难的。我想到的一种可能性是注册您自己的补间,在 pyramid_tm会话上执行刷新,获取 id,并在响应上设置 cookie。
我对这个问题表示同情,因为事务提交后发生的任何事情都是金字塔中真正的灰色区域,其中并不总是清楚会话不应被触及。我会记下来,以便将来继续思考如何改进 Pyramid 的这个工作流程。