2010-01-29 30 views
5

Mam kawałek kodu, który działa w tle proces, który wyglądaDjango i PostgreSQL transakcja wycofywania

from django.db import transaction 

try: 

    <some code> 

    transaction.commit() 

except Exception, e: 

    print e 

    transaction.rollback() 

W teście, złamię <some_code> z danymi, które powoduje błąd bazy danych. Wyjątek jest następujący:

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 

Tego oczekuję. Złe jest to, że nadal otrzymuję ten sam błąd, gdy próbuję uzyskać dostęp do DB po wywołaniu transaction.rollback. Co powinienem zrobić, aby przywrócić transakcję pomyślnie i sprawić, aby połączenie było znów użyteczne?

Btw, próbowałem również wstawić print connection.queries do debugowania kodu i zawsze zwraca pustą listę. Czy to możliwe, że Django używa innego połączenia DB?

Kod jest uruchamiany poza cyklem żądanie-odpowiedź. Próbowałem włączać i wyłączać TransactionMiddleware, ale nie dało to żadnego efektu.

Używam Django 1.1 i Postgres 8.4.

+0

Co się stanie, jeśli przeniesiesz "transaction.commit()" w klauzuli "else" instrukcji "try"? –

+0

To samo zachowanie. –

+0

Czy masz kontrolę nad serwerem DB? Jeśli włączasz rejestrowanie zapytań - "log_statement = all" (ALTER DATABASE SET log_statement TO "all"). Następnie spróbuj ponownie i spójrz na dziennik. –

Odpowiedz

6

Domyślnie TestCase nic nie wiedzą o transakcji, trzeba użyć TransactionalTestCase w tym przypadku.

+0

Dzięki, tęskniłem za tą odrobiną dokumentacji! –

2

Napisałem tego dekoratora na podstawie oprogramowania pośredniego do transakcji source. Mam nadzieję, że to pomaga, działa idealnie dla mnie.

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 
Powiązane problemy