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.rol开发者_如何转开发lback()
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.
Default TestCase does not know anything about transactions, you need to use TransactionalTestCase in this case.
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
精彩评论