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:
...
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.
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.
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
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