Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django and Postgres transaction rollback

I have a piece of code that works in a background process which looks like

from django.db import transaction

try:

    <some code>

    transaction.commit()

except Exception, e:

    print e

    transaction.rollback()

In a test, I break <some_code> with data that causes a database error. The exception is following

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

This is what I expect. The bad thing is that I still get the same error when I try to access the DB after transaction.rollback is called. What should I do to rollback the transaction succcessfully and make the connection usable once again?

Btw, I also tried inserting print connection.queries to debug the code, and it always returns an empty list. Could it be that Django is using some other DB connection?

The code is run outside of request-response cycle. I tried switching TransactionMiddleware on and off, but it gave no effect.

I am using Django 1.1 and Postgres 8.4.

like image 349
Dmitry Risenberg Avatar asked Jan 29 '10 12:01

Dmitry Risenberg


2 Answers

Default TestCase does not know anything about transactions, you need to use TransactionalTestCase in this case.

like image 158
Dmitry Shevchenko Avatar answered Oct 01 '22 09:10

Dmitry Shevchenko


I wrote this decorator based on the transaction middleware source. Hope it helps, works perfectly for me.

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
like image 22
Luiz Geron Avatar answered Oct 01 '22 08:10

Luiz Geron