Saltar al contenido

Django – Rollback save con transacción atomic

Solución:

Documentación de atomicidad

Para resumir, @transaction.atomic ejecutará una transacción en la base de datos si su vista produce una respuesta sin errores. Debido a que usted mismo está detectando la excepción, a Django le parece que su vista se ejecutó bien.

Si detecta la excepción, debe manejarla usted mismo: Control de transacciones

Si necesita producir una respuesta json adecuada en caso de falla:

from django.db import SomeError, transaction

def viewfunc(request):
    do_something()

    try:
        with transaction.atomic():
            thing_that_might_fail()
    except SomeError:
        handle_exception()

    render_response()

Sin embargo, si ocurre una excepción en una función decorada con transaction.atomic, entonces no tiene nada que hacer, se revertirá automáticamente al punto de guardado creado por el decorador antes de ejecutar su función, como se documenta:

atomic nos permite crear un bloque de código dentro del cual se garantiza la atomicidad en la base de datos. Si el bloque de código se completa con éxito, los cambios se confirman en la base de datos. Si hay una excepción, los cambios se revierten.

Si la excepción está atrapada en un bloque except, entonces debe volverse a generar para que atomic la detecte y realice la reversión, es decir:

    try:
        some_object = SomeModel(...)
        some_object.save()

        if something:
            raise exception.NotAcceptable()
            # When the workflow comes into this condition, I think the previous save should be undome
            # Whant am I missing?

    except exception.NotAcceptable, e:
        # do something
        raise  # re-raise the exception to make transaction.atomic rollback

Además, si desea más control, puede retroceder manualmente al punto de guardado establecido previamente, es decir:

class MyView(View):
    def post(self, request, *args, **kwargs):
        sid = transaction.savepoint()
        some_object = SomeModel(...)
        some_object.save()

        if something:
            transaction.savepoint_rollback(sid)
        else:
            try:
                # In worst case scenario, this might fail too
                transaction.savepoint_commit(sid)
            except IntegrityError:
                transaction.savepoint_rollback(sid)

Para mí, esto funciona en Django 2.2.5

Primero que nada en tu settings.py

...

DATABASES = {
    'default': {
        'ENGINE': 'xxx',  # transactional db
        ...
        'ATOMIC_REQUESTS': True,
    }
}

Y en tu función (views.py)

from django.db import transaction

@transaction.atomic
def make_db_stuff():

    # do stuff in your db (inserts or whatever)

    if success:
        return True
    else:
        transaction.set_rollback(True)
        return False
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *