Scott Stafford
Scott Stafford

Reputation: 44818

Using nested Django transaction.atomic() to handle exceptions?

Django's docs say this about transaction.atomic() and exceptions:

https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic

Avoid catching exceptions inside atomic!

...

The correct way to catch database errors is around an atomic block as shown above. If necessary, add an extra atomic block for this purpose. This pattern has another advantage: it delimits explicitly which operations will be rolled back if an exception occurs.

...

What does "If necessary, add an extra atomic block for this purpose." look like? Can I do this or does this cause "unexpected behavior"?

valid = True
errors = []
objects = MyModel.objects.all()
try:
    with transaction.atomic():
        for obj in objects:
            try:
                # Update and save obj here...
            except:
                errors.append("obj {} had errors".format(obj.pk))
                valid = False
        if not valid:
            raise Exception('batch update failed.')

except Exception as ex:
    # Handle it..

Do they mean to write it like this? If so, why is this different?

valid = True
errors = []
objects = MyModel.objects.all()
try:
    with transaction.atomic():
        for obj in objects:
            try:
                with transaction.atomic():  # Here's my 'extra atomic block'
                    # Update and save obj here...
            except:
                errors.append("obj {} had errors".format(obj.pk))
                valid = False
        if not valid:
            raise Exception('batch update failed.')

except Exception as ex:
    # Handle it..

Upvotes: 0

Views: 1884

Answers (1)

Domen Blenkuš
Domen Blenkuš

Reputation: 2242

Django triggers rolback only when transaction block catches DatabaseError (or its subclass), So you shouldn't catch it before it. If you add second transaction block (your 2nd example), error is caught, transaction is marked to rollbacked, and then you can do whatever you want.

I think that you should be good it yo re-raise exactly the same error, but this is just a guess.

Upvotes: 1

Related Questions