I have the following piece of code overriding the save method of a model:
@transaction.commit_on_success
def save(self, *args, **kwargs):
try:
transaction.commit()
self.qa.vote_down_count += 1
self.qa.save()
super(self.__class__, self).save(*args, **kwargs)
except:
transaction.rollback()
raise
else:
transaction.commit()
The expected behavior would be: self.qa attribute vote_down_count is incremented by one, but if any exception occurs in the super(self) save method the transaction rollbacks (that means the self.qa.vote_down_count += 1 is not committed in the database).
The actual behavior is: self.qa.vote_down_count += 1 is committed to database even if an IntegrityError exception raises from super(self) save.
Any thoughs?
Why not simply do:
@transaction.commit_manually
def save(self, *args, **kwargs):
try:
super(self.__class__, self).save(*args, **kwargs)
self.qa.vote_down_count += 1
self.qa.save()
except:
transaction.rollback()
raise
else:
transaction.commit()
This is how the docs imply to do it, though they say to do this in your view function, so you might not need the @transaction.commit_manually
on the save()
method, instead putting it on the view.
Try to use savepoints. Something like this:
def save(self, *args, **kwargs):
try:
sid = transaction.savepoint()
self.qa.vote_down_count += 1
self.qa.save()
super(self.__class__, self).save(*args, **kwargs)
except:
transaction.rollback(sid)
raise
else:
transaction.commit(sid)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With