2011-11-29 111 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

相關問題