在SQLAlchemy会话持久化之前删除该对象

Cam*_*son 20 python sqlalchemy

我的应用程序允许用户创建和删除Site对象.我使用session.add()和实现了这个session.delete().然后,我有"保存"和"重置"是呼叫按钮session.commit()session.rollback().

如果我添加一个新的Site,然后保存/提交它,然后删除它,一切正常.但是,如果我尝试在保存之前从会话中删除对象,则会出现"非持久性"错误.

码:

self.newSite = Site('foo')
self.session.add(self.newSite)
print self.session.new
self.session.delete(self.newSite)
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

我理解这里发生了什么,但我不确定我应该做什么.

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

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

zzz*_*eek 16

你可以Session.expunge().我认为这样做的理由delete()是,如果你发送一个待处理的东西,你担心你不会跟踪事情.但我可以看到故事的另一面,我会考虑一下.基本上隐含的状态delete()包括一些持久性的假设,但它们可能没有我想的那么重要.然后会想到一个"删除或删除"方法,这很有趣,基本上是我们最初从Hibernate复制的"保存或更新",它刚刚成为"添加"."add"可以执行transient-> pending以及detached-> persistent的转换 - 潜在的"remove()"是否同时执行pending-> transient和persistent->删除?范围内的会话已经有"删除()"....

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

有趣的是,如果您rollback()在会话中,无论您add()在该会话中进行了什么操作,无论是否刷新,都会被清除.

  • 我可能会说"if session in session.new:expunge else:delete" (6认同)
  • 我同意迈克的看法,"删除"可能更宽容.但是,目前的情况已经大大简化了 - 可能有其他相关的对象明确地或隐含地(通过关系)被添加到同一个会话中而没有被提交.因此,IMO,最干净的方法是在会话上执行`rollback()`. (3认同)