Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting an object from an SQLAlchemy session before it's been persisted

Tags:

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).

like image 822
Cam Jackson Avatar asked Nov 29 '11 05:11

Cam Jackson


People also ask

What function from the Session object is used to delete items in SQLAlchemy?

delete() is invoked upon an object and the Session is flushed, the row is deleted from the database.

What does flush do SQLAlchemy?

flush() communicates a series of operations to the database (insert, update, delete). The database maintains them as pending operations in a transaction.

What does First () do in SQLAlchemy?

first() applies a limit of one within the generated SQL, so that only one primary entity row is generated on the server side (note this may consist of multiple result rows if join-loaded collections are present). Calling Query. first() results in an execution of the underlying query.

What does Session refresh do SQLAlchemy?

You can use session. refresh() to immediately get an up-to-date version of the object, even if the session already queried the object earlier.


1 Answers

You can Session.expunge() it. I think the rationale with delete() 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 by delete() 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 wanted delete() to work on a pending, we'd just change that assertion.

Interestingly, if you rollback() the session, whatever you've add()'ed within that session, whether or not it got flushed, is expunged.

like image 57
zzzeek Avatar answered Sep 17 '22 11:09

zzzeek