我已经看过以前有类似问题的人的例子,但是我似乎不明白为什么我的问题不能解决,因为我使用的是同一个会话。在
这是我的代码块,它简单地查询数据库以查看是否存在客户,然后在另一个insert中使用该客户。但是当我一碰到transaction.commit()
行,它就会抛出DetachedInstanceError
。这可能是来自另一个方法中较早的transaction.commit()
吗?在
@view_config(route_name='create_location', renderer='templates/main.html')
def create_location(request):
#get the json data from the ajax call
data = request.json_body
session = DBSession
locationName = data["location"]
custID = data["custID"]
Customer = session.query(TCustomer).filter(TCustomer.ixCustomer==custID).one()
#create customer
Location = TLocation(sDescription=locationName, ixCustomer=Customer)
session.add(Location)
session.flush()
transaction.commit()
return Response('ok')
这是我的演讲:
^{pr2}$
解决方案如下:
必须添加
keep_session=True
然后我不用做
session = DBSession()
我只需要使用DBSession
进行查询和会话工作是,如果在同一请求-响应周期内调用另一个方法-一旦提交事务,SQLAlchemy无法保证内存中的ORM对象仍然代表数据库的实际状态,因此,如果不显式地将现在分离的对象合并到新的会话中,就不能在一个事务中获取对象并将其保存回另一个事务中。在
您通常不应该在代码中使用
transaction.commit()
。使用ZopeTransactionExtension
背后的想法是它将SQLAlchemy事务与Pyramid的请求-响应周期联系在一起-当请求启动时,将构造一个新的会话,如果请求在视图中提交失败,则返回。在代码中,您不应该关心提交任何内容—只需将新对象添加到会话中:(忍不住让代码更像“普通”Python代码。。。匈牙利符号是。。。呃。。。现在不是很常用。。。谢谢你给了我一个怀旧的闪回:))见PEP 8详情)。
在很少的情况下,您可能希望请求的某些部分成功,或者甚至只在发生错误时才将数据保存到数据库(例如,将错误记录到数据库中)。在这些情况下,您将使用一个单独的会话,该会话没有配置ZopeTransactionExtension。您需要手动提交此类会话:
^{pr2}$进一步阅读:
When do I construct a Session, when do I commit it, and when do I close it?-SQLAlchemy文档中的高级概述。”TL;DR:一般来说,将会话的生命周期与访问和/或操作数据库数据的函数和对象分开并在外部进行。”请注意,金字塔已经为您完成了所有的会话管理—独立于代码的外部结束。
Databases Using SQLAlchemy-一个使用SQLAlchemy的基本金字塔应用程序。请参见
dev wikipage_add()
函数,以获取将一些数据保存到数据库的典型代码的示例。相关问题 更多 >
编程相关推荐