Nested transactions are database-specific, so you're going to lose portability. If you need that, I'd consider doing is changing the simple @commit_on_save for something more flexible:
def save(commit=True):
if commit:
db.start_transaction()
try:
self.real_save()
db.commit_transaction()
except backend.DatabaseError, e:
db.rollback_transaction()
raise e
else:
self.real_save()
Otherwise, you can run arbitrary SQL commands so you can call db.connection.cursor().execute()
with whatever your backend database uses, probably with a check to not do anything for other backends so you can still use sqlite for local testing.
Depending on your app structure, it might also be possible to use savepoints. I've written a few utilities which do something like this:
- Start transaction
- Perform mandatory commands
- Start optional statements:
- start savepoint
- execute
- savepoint commit or rollback
- More mandatory SQL
- commit