Correct way to transaction.rollback () with throwing exception in django
I am working with Django 1.7.1 and python 2.7, I am making several POST requests that need to be inside a transaction, in fact I am using a @transaction.atomic()
decorator that does the whole function inside a transaction.
As far as I know, this decorator is similar to commit_on_success
and does rollback when a database error occurs.
Is it possible to throw a custom exception that rolls back a transaction but doesn't use savepoints? I want to return an HttpResponse when a rollback is in progress explaining why the transaction was not completed.
I have it.
@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:
...
source to share
In this case - remove the decorator, you can wrap some of the code in your view:
try:
with transaction.atomic():
# ...
if mal != '':
raise IntegrityError
except IntegrityError:
handle_exception()
Any operations taken internally atomic
will already be safely discarded by calling handle_exception ().
https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.atomic
source to share
I set my db to 'ATOMIC_REQUESTS'
so every request is nested within a transaction too.
I was looking for a way to rollback without throwing an exception. I know not the original question, but the following worked for the record (django 1.11):
from django.db import transaction
def my_view(request):
# some db interactions
if it_hit_the_fan:
transaction.set_rollback(True)
# return response
source to share