[Fixed]-Is it ok to catch and reraise an exception inside Django transaction.atomic()?

7👍

Based on the docs, I would ensure that the correct Exception gets re-raised, others errors you might handle independently. For django it is only necessary that it gets notified regarding things that went wrong when talking to the database.

with transaction.atomic():
    # something
    try:
        # something
    except DatabaseError as db_err:
        logger.exception("Report error here.")
        raise db_err
    except Exception:
        # do something else
        # no need to reraise
        # as long as you handle it properly and db integrity is guaranteed

4👍

Is it okay to do this or does this cause “unexpected behavior”?

with transaction.atomic():
    # something
    try:
        # something
    except:
        logger.exception("Report error here.")
        raise

Except for the bare except clause (you want at least except Exception:), this is ok, assuming your logger doesn’t touch the database (which would be a very bad idea anyway) and the logger call doesn’t raise another exception (in which case I have no idea what will actually happen).

But you’d get the same result inverting the transaction.atomic() block and the try/except, ie:

try:
    with transaction.atomic():
        # something
        # something
except Exception:
    logger.exception("Report error here.")
    raise

4👍

This example will clear your doubt.

with transaction.atomic():
    try:
        # if you do something that raises ONLY db error. ie. Integrity error
    except Exception:
        # and you catch that integrity error or any DB error like this here.
        # now if you try to update your DB
        model = Model.objects.get(id=1)
        model.description = "new description"
        model.save()
        # This will be illegal to do and Django in this case 
        # will raise TransactionManagementError suggesting 
        # you cannot execute any queries until the end of atomic block.

Now in case you are raising your custom exception like this:

with transaction.atomic():
    try:
        # raising custom exception
        raise Exception("some custom exception")
    except Exception:
        # and you catch that exception here
        # now if you try to update your DB
        model = Model.objects.get(id=1)
        model.description = "new description"
        model.save()
        # Django will allow you to update the DB.

Leave a comment