Mi aplicación permite a los usuarios crear y eliminar objetos Site
. Lo he implementado usando session.add()
y session.delete()
. entonces tengo 'Guardar' y 'reset' botones que llaman session.commit()
y session.rollback()
.La eliminación de un objeto a partir de una sesión de SQLAlchemy antes de que se haya persistido
Si agrego un nuevo Site
, a continuación, guardar/cometerlo, y luego eliminarlo, todo va bien. Sin embargo, si trato de eliminar un objeto de la sesión antes de que se haya guardado, aparece el error "no persistido".
Código:
self.newSite = Site('foo')
self.session.add(self.newSite)
print self.session.new
self.session.delete(self.newSite)
Salida:
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
entiendo lo que está pasando aquí, pero no estoy seguro de lo que debería estar haciendo en su lugar.
¿Hay algún otro método de eliminación de un objeto que aún no es persistido-de una sesión? ¿O debería llamar al session.flush()
antes de intentar una eliminación, en caso de que el objeto que deseo eliminar aún no haya sido eliminado?
Si es el último, ¿cómo es que session.query()
auto-flushes (asegurando que los objetos pendientes aparecen en los resultados de la consulta), pero session.delete()
no (que aseguraría que los objetos pendientes puedan eliminarse sin error).
Estoy de acuerdo con Mike que 'delete' podría ser más indulgente. Sin embargo, la situación actual se ha simplificado mucho: podría haber otros objetos relacionados que se hayan agregado explícita o implícitamente (a través de relaciones) a la misma sesión y no se hayan comprometido. Por lo tanto, IMO, la forma más limpia es hacer un 'rollback()' en la sesión. – van
Gracias, eso tiene sentido ahora. Entonces, cuando se hace clic en el botón Eliminar, ¿cuál debería ser la lógica? Algo como 'try: session.delete (foo); excepto InvalidRequestError: session.expunge (foo) '? O, según [esta respuesta] (http://stackoverflow.com/a/3897845/665488), tal vez: 'if has_identity (foo): session.delete (foo); else: session.expunge (foo) '? –
Probablemente diría "if object in session.new: expunge else: delete" – zzzeek