Django transactions: managing two different transactions atomically inside the overriding of save() method

966 views Asked by At

In Django 1.4 I have a code like the following:

from django.db import models
from django.db import transaction

class MyModel(models.Model):
    # model definition

    @transaction.commit_manually
    def save(self, *args, **kwargs):
        try:
            super(MyModel, self).save(*args, **kwargs)
            do_other_things()
        except:
            transaction.rollback()
            raise
        else:
            transaction.commit()
            obj2 = MySecondModel(mymodel = self, foo = "bar")
            obj2.save()


class MySecondModel(models.Model):
    myModelId = models.ForeignKey(MyModel)
    # other fields defining this model

As you can see, after creating an object of MyModel class, I have to create also another object of MySecondModel class, that has a reference to the first one.

In the code above, if something went wrong during obj2.save(), there would be no way to rollback the first transaction.

How can I handle those two transactions as a unique atomic transaction?

1

There are 1 answers

0
floatingpurr On BEST ANSWER

As suggested by Gocht in the comments under the question, a solution in Django 1.4 is using @transaction.commit_on_success(). The code could be something like this:

from django.db import models
from django.db import transaction

class MyModel(models.Model):
    # model definition

    @transaction.commit_on_success()
    def save(self, *args, **kwargs):
        try:
            super(MyModel, self).save(*args, **kwargs)
            do_other_things()
            obj2 = MySecondModel(mymodel = self, foo = "bar")
            obj2.save()
        except:
            print 'exception'
            raise
        else:
            print 'job done'



class MySecondModel(models.Model):
    myModelId = models.ForeignKey(MyModel)
    # other fields defining this model