Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way of transaction.rollback() with raise exception in django

I am working with Django 1.7.1 and python 2.7, I am doing some POST requests that requires to be inside a transaction, actually I am using @transaction.atomic() decorator that makes the entire function to be inside a transaction.

As far as I know, this decorator is similar to commit_on_success and makes a rollback if a database error is raised.

Is it possible to raise a custom exception that makes the transaction to rollback but not using save points? I want to return a HttpResponse when the rollback is done, explaining why the transaction was not completed.

I have this.

@transaction.atomic()
def salida_de_almacen(request):
    if request.method == 'POST':
        try:
            folio = request.POST['folio'] #Folio de la orden
            epccoma = request.POST['epc'] #EPCs separados por coma
            if folio is None or epccoma is None:
                return HttpResponse('Datos Incompletos',status=400)
            detalles = ODetalle.objects.filter(orden__folio=folio)
            epcs = epccoma.replace(' ','').split(',')
            inventario = Inventario.objects.filter(epc__in=epcs)
            mal = '' # Items incompletos
            for d in detalles:
                for i in inventario:
                    if i.producto.item == d.producto.item:
                        d.cantidad_entregada+=i.cantidad                        
                        i.delete()
                if d.cantidad_entregada<d.cantidad_ordenada:
                    mal+='%s,' % d.producto.item
            if mal != '':

         >>>>   #raise Exception??  <<<<---- I WANT TO RISE AN EXCEPTION HERE TO ROLLBACK THE TR. 

                return HttpResponse('Items Incompletos: '+mal,status=400)
            for d in detalles:
                d.status=2 #Status completo
                d.save()
            return HttpResponse(serial_folio,status=200) # Todo bien
        except Exception as e:
            return  HttpResponse(e.message,status=500)    
    else:
        ...
like image 626
Alex Lord Mordor Avatar asked Nov 13 '14 20:11

Alex Lord Mordor


People also ask

How do I rollback a transaction in Django?

If an exception occurs, Django will perform the rollback when exiting the first parent block with a savepoint if there is one, and the outermost block otherwise. Atomicity is still guaranteed by the outer transaction. This option should only be used if the overhead of savepoints is noticeable.

How does Django handle concurrency?

In terms of Django, optimistic concurrency control can be implemented by overriding the save method on your model class... And, of course, for either of these concurrency mechanisms to be robust, you have to consider transactional control.


1 Answers

In this case - remove decorator, you can wrap part of code in your view:

try:
    with transaction.atomic():
        # ...
        if mal != '':
            raise IntegrityError

except IntegrityError:
    handle_exception()

Any operations attempted inside atomic will already have been rolled back safely when handle_exception() is called.

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

like image 181
madzohan Avatar answered Sep 21 '22 07:09

madzohan