2011-11-29 62 views
15

我的应用程序允许用户创建和删除Site对象。我已经使用session.add()session.delete()执行了此操作。然后我有'保存'和'重置'按钮,调用session.commit()session.rollback()从SQLAlchemy会话中删除一个对象,然后保存它

如果我添加一个新的Site,然后保存/提交它,然后删除它,一切都会好的。但是,如果我在保存之前尝试从会话中删除对象,则会收到“未保留”错误。

代码:

self.newSite = Site('foo') 
self.session.add(self.newSite) 
print self.session.new 
self.session.delete(self.newSite) 

输出:

IdentitySet([<Site('foo')>]) 

Traceback (most recent call last): 
    File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_comm.py", line 744, in doIt 
    result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec) 
    File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_vars.py", line 375, in evaluateExpression 
    result = eval(compiled, updated_globals, frame.f_locals) 
    File "<string>", line 1, in <module> 
    File "C:\Python27\Lib\site-packages\sqlalchemy\orm\session.py", line 1245, in delete 
    mapperutil.state_str(state)) 
InvalidRequestError: Instance '<Site at 0x1ed5fb0>' is not persisted 

我知道这里发生了什么,但我不知道我应该不是做。

是否有其他方法从会话中删除尚未保留的对象?或者我应该在尝试删除之前调用session.flush(),以防我想删除的对象没有被刷新?

如果是后者,session.query()如何自动刷新(确保挂起的对象出现在查询结果中),但session.delete()不会(这将确保挂起的对象可以被删除而不会出错)。

回答

13

你可以Session.expunge()它。我认为delete()就是这样的基本原理,它担心如果您发送一个待处理的内容,则无法跟踪事件。但我可以看到故事的另一面,我会考虑这个。基本上,delete()暗含的状态包含一些持久性假设,但它们可能不像我想的那么重要。然后出现一个“删除或删除”的方法,这很有趣,基本上是我们最初从Hibernate中复制的“保存或更新”,它刚刚变成了“添加”。 “add”可以执行transient-> pending以及detached-> persistent的转换 - 潜在的“remove()”会执行pending-> transient和persistent->删除吗?太差的范围会话已经有“删除()”....

Session.query()自动刷新,因为它即将出去的数据库发出一些SQL来获取一些行;所以无论你在当地需要先走出去。 delete()只是标记对象的状态,因此不需要调用任何SQL。如果我们想要delete()来处理待处理的问题,那么我们只需更改该断言。

有趣的是,如果你rollback()会话,无论你在该会话中编辑了add(),它是否被刷新,都会被清除。

+3

我同意Mike的说法,“删除”可以更宽容。然而,现在的情况大大简化了 - 可能有其他相关对象明确地或隐含地(通过关系)添加到同一个会话中而没有被提交。因此,IMO最简洁的方法是在会话上执行'rollback()'。 – van

+0

谢谢,现在有道理。所以当点击删除按钮时,逻辑应该是什么?像'try:session.delete(foo);除了InvalidRequestError:session.expunge(foo)'?或者,根据[这个答案](http://stackoverflow.com/a/3897845/665488),也许:'如果has_identity(foo):session.delete(foo); else:session.expunge(foo)'? –

+5

我可能会说“如果session.new中的对象:expunge else:delete” – zzzeek

相关问题