从SQLAlchemy会话中删除一个对象,然后保存它
我的应用程序允许用户创建和删除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()
不会(这将确保挂起的对象可以被删除而不会出错)。
你可以Session.expunge()
它。我认为delete()
就是这样的基本原理,它担心如果您发送一个待处理的内容,则无法跟踪事件。但我可以看到故事的另一面,我会考虑这个。基本上,delete()
暗含的状态包含一些持久性假设,但它们可能不像我想的那么重要。然后出现一个“删除或删除”的方法,这很有趣,基本上是我们最初从Hibernate中复制的“保存或更新”,它刚刚变成了“添加”。 “add”可以执行transient-> pending以及detached-> persistent的转换 - 潜在的“remove()”会执行pending-> transient和persistent->删除吗?太差的范围会话已经有“删除()”....
Session.query()
自动刷新,因为它即将出去的数据库发出一些SQL来获取一些行;所以无论你在当地需要先走出去。 delete()
只是标记对象的状态,因此不需要调用任何SQL。如果我们想要delete()
来处理待处理的问题,那么我们只需更改该断言。
有趣的是,如果你rollback()
会话,无论你在该会话中编辑了add()
,它是否被刷新,都会被清除。
我同意Mike的说法,“删除”可以更宽容。然而,现在的情况大大简化了 - 可能有其他相关对象明确地或隐含地(通过关系)添加到同一个会话中而没有被提交。因此,IMO最简洁的方法是在会话上执行'rollback()'。 – van
谢谢,现在有道理。所以当点击删除按钮时,逻辑应该是什么?像'try:session.delete(foo);除了InvalidRequestError:session.expunge(foo)'?或者,根据[这个答案](http://*.com/a/3897845/665488),也许:'如果has_identity(foo):session.delete(foo); else:session.expunge(foo)'? –
我可能会说“如果session.new中的对象:expunge else:delete” – zzzeek