If the save fails due to a database error (e.g. integrity violation,
timeout...) it raises an exception. At this point, any new queries will
fail with the error
psycopg2.ProgrammingError: current transaction is aborted, commands
ignored until end of transaction block
Basically the Postgres transaction is dead and has to be rolled back
before any new queries can be executed.
ISTM the Model.save() method itself could rollback the (implicit)
transaction when there is an error, something like
try:
... normal save code
except DatabaseError:
transaction.rollback_unless_managed()
raise
I have seen a bit of discussion of this in the list archives and Trac
but I haven't found any good solutions. Wrapping every save() in a try
block similar to the above seems very clumsy, as is wrapping every
save() in an explicit transaction block.
So, my questions are
- how do others deal with this?
- what is considered best practice, if anything?
- does it make sense to alter Model.save(), or my own model's save(), as
indicated above?
Thanks,
Kent
try:
Model.save(self)
except DatabaseError:
transaction.rollback_unless_managed()
raise
The benefits:
- automatic recovery from failed unmanaged transactions - very handy
when working in the shell, or when performing multiple updates that
don't have to succeed or fail as a group
- no effect when inside an explicit (managed) transaction
Thanks,
Kent