在持久化之前从 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)
输出:
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()
却没有' t(这将确保可以毫无错误地删除挂起的对象)。
My application allows users to create and delete Site
objects. I have implemented this using session.add()
and session.delete()
. I then have 'Save' and 'Reset' buttons that call session.commit()
and session.rollback()
.
If I add a new Site
, then save/commit it, and then delete it, everything goes OK. However, if I try to remove an object from the session before it's been saved, I get a 'not persisted' error.
Code:
self.newSite = Site('foo')
self.session.add(self.newSite)
print self.session.new
self.session.delete(self.newSite)
Output:
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
I understand what's happening here, but I'm not sure what I should be doing instead.
Is there some other method of removing a not-yet-persisted object from a session? Or should I be calling session.flush()
before attempting a deletion, in case the object I want to delete hasn't been flushed yet?
If it's the latter, how come session.query()
auto-flushes (ensuring that pending objects show up in the query results), but session.delete()
doesn't (which would ensure that pending objects can be deleted without error).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以
Session.expunge()
它。我认为delete()
这样做的理由是,如果您将其发送为待处理,它会担心您无法跟踪事物。但我可以看到故事的另一面,我会考虑一下。基本上,delete()
隐含的状态包括一些持久性假设,但它们可能没有我想象的那么重要。然后我想到了“清除或删除”方法,这很有趣,这基本上是我们最初从 Hibernate 复制的“保存或更新”方法,它只是变成了“添加”。 “add”可以进行瞬态 -> 待定以及分离 -> 持久的转换 - 潜在的“remove()”会同时进行待定 -> 瞬态和持久 -> 删除吗?太糟糕了,作用域会话已经有“remove()”......Session.query()
自动刷新,因为它即将发送到数据库以发出一些 SQL 来获取一些行;所以无论你当地有什么,都需要先出去。delete()
只是标记对象的状态,因此无需调用任何 SQL。如果我们想让delete()
处理挂起的任务,我们只需更改该断言即可。有趣的是,如果您
rollback()
会话,那么您在该会话中add()
所做的任何操作,无论它是否被刷新,都会被删除。You can
Session.expunge()
it. I think the rationale withdelete()
being that way is, it worries you're not keeping track of things if you send it a pending. But I can see the other side of the story on that, I'll think about it. Basically the state implied bydelete()
includes some assumptions of persistence but they're probably not as significant as I'm thinking. An "expunge or delete" method then comes to mind, which is funny that's basically the "save or update" we originally copied from Hibernate, which just became "add". "add" can do the transitions of transient->pending as well as detached->persistent - would a potential "remove()" do both pending->transient and persistent->deleted ? too bad the scoped session already has "remove()"....Session.query()
autoflushes because it's about to go out to the database to emit some SQL to get some rows; so whatever you have locally needs to go out first.delete()
just marks the state of an object so there's no need to invoke any SQL. If we wanteddelete()
to work on a pending, we'd just change that assertion.Interestingly, if you
rollback()
the session, whatever you'veadd()
'ed within that session, whether or not it got flushed, is expunged.