首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DetachedInstanceError:实例< 0x428ddf0>中的TCustomer不绑定到会话

DetachedInstanceError:实例< 0x428ddf0>中的TCustomer不绑定到会话
EN

Stack Overflow用户
提问于 2014-05-30 19:12:37
回答 2查看 1.3K关注 0票数 1

我看过以前有类似问题的人的例子,但是我似乎不明白为什么我的例子不能工作,因为我使用的是同一个会话。

这是我的代码块,它只是查询数据库以查看客户是否存在,然后在另一个插入中使用该客户。但是,一旦我到达线,transaction.commit(),它抛出DetachedInstanceError。这可能来自于另一种方法中的早期transaction.commit()吗?

代码语言:javascript
复制
@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')

这是我的DBSession:

代码语言:javascript
复制
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-30 19:35:53

以下是解决办法:

代码语言:javascript
复制
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension(keep_session=True)))

必须添加keep_session=True

然后,我所要做的不是做session = DBSession(),而是在查询和会话工作中使用DBSession

票数 0
EN

Stack Overflow用户

发布于 2014-05-31 18:53:29

这可能来自于另一个方法中的早期transaction.commit()吗?

是的,,如果在同一个请求-响应周期内调用另一个方法,那么一旦事务提交,SQLAlchemy就不能保证任何内存中的ORM对象仍然代表数据库的实际状态,所以您不能只在一个事务中获取一个对象并将它保存回另一个事务中,而不显式地将现在分离的对象合并到一个新会话中。

您通常不应该在代码中使用transaction.commit() 。使用ZopeTransactionExtension的思想是,它将SQLAlchemy事务与金字塔的请求-响应周期联系起来--在请求启动时构造一个新会话,如果请求成功或回滚,则在请求失败时提交(即在您的视图中引发异常)。在您的代码中,您不应该担心提交任何内容--只需将新对象添加到会话中:

代码语言:javascript
复制
@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

    customer = DBSession.query(Customer).filter(Customer.id==data["custID"]).one()
    session.add(Location(description=data["location"], customer=customer))

    return Response('ok')

(忍不住让代码更像“普通”Python代码.匈牙利符号是..。呃..。现在不太常用..。(谢谢你给我一个怀旧的闪回:))(详见http://legacy.python.org/dev/peps/pep-0008/ )。

在罕见的情况下,您可能希望请求的某些部分无论如何都成功,甚至只有在发生错误时才希望将数据保存到数据库(对数据库的日志错误可能是一个例子)。在这些情况下,您使用了一个单独的会话,它是在没有ZopeTransactionExtension的情况下配置的。您需要手动提交这样的会话:

代码语言:javascript
复制
try:
    do_something_which_might_fail()
except Exception as e:
    session = ErrorLogSession()
    session.add(SomeORMObject(message=format_exception(e))
    session.commit()

进一步读:

  • 何时构造会话,何时提交会话,何时关闭会话? -a在SQLAlchemy文档中的高级别概述。TL;DR:通常情况下,将会话的生命周期与访问和/或操作数据库数据的函数和对象隔离开来。请注意,金字塔已经为您完成了所有的会话管理--从外部结束,与代码分开。
  • 使用SQLAlchemy的数据库 -一个使用SQLAlchemy的基本金字塔应用程序。有关将一些数据保存到数据库的典型代码示例,请参见dev wikipage_add()函数。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23961871

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档