2010-01-29 31 views
5

que tienen un pedazo de código que funciona en un proceso en segundo plano que se parece aDjango y Postgres rollback de transacciones

from django.db import transaction 

try: 

    <some code> 

    transaction.commit() 

except Exception, e: 

    print e 

    transaction.rollback() 

En una prueba, yo romper <some_code> con los datos que causa un error de base de datos. La excepción es siguiente

File "/home/commando/Development/Diploma/streaminatr/stream/testcases/feeds.py", line 261, in testInterrupt 

    form.save(self.user1)                      

File "/usr/lib/pymodules/python2.5/django/db/transaction.py", line 223, in _autocommit      

    return func(*args, **kw)                     

File "/home/commando/Development/Diploma/streaminatr/stream/forms.py", line 99, in save      

    print(models.FeedChannel.objects.all())                 

File "/usr/lib/pymodules/python2.5/django/db/models/query.py", line 68, in `__repr__ `      

    data = list(self[:REPR_OUTPUT_SIZE + 1])                 

File "/usr/lib/pymodules/python2.5/django/db/models/query.py", line 83, in `__len__ `       

    self._result_cache.extend(list(self._iter))                

File "/usr/lib/pymodules/python2.5/django/db/models/query.py", line 238, in iterator      

    for row in self.query.results_iter():                  

File "/usr/lib/pymodules/python2.5/django/db/models/sql/query.py", line 287, in results_iter    

    for rows in self.execute_sql(MULTI):                  

File "/usr/lib/pymodules/python2.5/django/db/models/sql/query.py", line 2369, in execute_sql    

    cursor.execute(sql, params)                    

InternalError: current transaction is aborted, commands ignored until end of transaction block 

Esto es lo que espero. Lo malo es que todavía obtengo el mismo error cuando intento acceder al DB después de llamar al transaction.rollback. ¿Qué debo hacer para deshacer la transacción correctamente y hacer que la conexión se pueda utilizar una vez más?

Por cierto, también intenté insertar print connection.queries para depurar el código, y siempre devuelve una lista vacía. ¿Podría ser que Django está usando alguna otra conexión DB?

El código se ejecuta fuera del ciclo de solicitud-respuesta. Traté de activar y desactivar TransactionMiddleware, pero no dio ningún efecto.

Estoy usando Django 1.1 y Postgres 8.4.

+0

¿Qué sucede si mueve "transaction.commit()" en la cláusula "else" de la declaración "try"? –

+0

Solo el mismo comportamiento. –

+0

¿Tiene control sobre el servidor de bases de datos? Si activa el registro de consultas - "log_statement = all" (ALTER DATABASE SET log_statement TO 'all'). Luego vuelva a intentarlo y eche un vistazo al registro. –

Respuesta

6

defecto caso_prueba no sabe nada acerca de las transacciones, es necesario utilizar TransactionalTestCase en este caso.

+0

¡Gracias, me perdí esta documentación! –

2

Escribí este decorador basado en el middleware de transacción source. Espero que ayude, funciona perfectamente para mí.

def djangoDBManaged(func): 
    def f(*args, **kwargs): 
     django.db.transaction.enter_transaction_management() 
     django.db.transaction.managed(True) 
     try: 
      rs = func(*args, **kwargs) 
     except Exception: 
      if django.db.transaction.is_dirty(): 
       django.db.transaction.rollback() 
      django.db.transaction.leave_transaction_management() 
      raise 
     finally: 
      if django.db.transaction.is_managed(): 
       if django.db.transaction.is_dirty(): 
        django.db.transaction.commit() 
       django.db.transaction.leave_transaction_management() 
     return rs 
    # So logging gets the right call info whatever the decorator order is 
    f.__name__ = func.__name__ 
    f.__doc__ = func.__doc__ 
    f.__dict__ = func.__dict__ 
    return f 
Cuestiones relacionadas