2013-03-06 18:12:24 +08:00
|
|
|
import warnings
|
|
|
|
|
|
|
|
from django.core.exceptions import MiddlewareNotUsed
|
|
|
|
from django.db import connection, transaction
|
2014-02-27 05:48:20 +08:00
|
|
|
from django.utils.deprecation import RemovedInDjango18Warning
|
2006-05-02 09:31:56 +08:00
|
|
|
|
2013-11-03 04:12:09 +08:00
|
|
|
|
2006-06-08 13:00:13 +08:00
|
|
|
class TransactionMiddleware(object):
|
2006-05-02 09:31:56 +08:00
|
|
|
"""
|
|
|
|
Transaction middleware. If this is enabled, each view function will be run
|
|
|
|
with commit_on_response activated - that way a save() doesn't do a direct
|
|
|
|
commit, the commit is done when a successful response is created. If an
|
|
|
|
exception happens, the database is rolled back.
|
|
|
|
"""
|
2013-03-06 18:12:24 +08:00
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
warnings.warn(
|
|
|
|
"TransactionMiddleware is deprecated in favor of ATOMIC_REQUESTS.",
|
2014-02-27 05:48:20 +08:00
|
|
|
RemovedInDjango18Warning, stacklevel=2)
|
2013-03-06 18:12:24 +08:00
|
|
|
if connection.settings_dict['ATOMIC_REQUESTS']:
|
|
|
|
raise MiddlewareNotUsed
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
def process_request(self, request):
|
|
|
|
"""Enters transaction management"""
|
|
|
|
transaction.enter_transaction_management()
|
|
|
|
|
|
|
|
def process_exception(self, request, exception):
|
|
|
|
"""Rolls back the database and leaves transaction management"""
|
|
|
|
if transaction.is_dirty():
|
2013-02-06 05:52:29 +08:00
|
|
|
# This rollback might fail because of network failure for example.
|
|
|
|
# If rollback isn't possible it is impossible to clean the
|
|
|
|
# connection's state. So leave the connection in dirty state and
|
|
|
|
# let request_finished signal deal with cleaning the connection.
|
2006-05-02 09:31:56 +08:00
|
|
|
transaction.rollback()
|
|
|
|
transaction.leave_transaction_management()
|
|
|
|
|
|
|
|
def process_response(self, request, response):
|
|
|
|
"""Commits and leaves transaction management."""
|
2013-03-04 22:24:01 +08:00
|
|
|
if not transaction.get_autocommit():
|
2006-05-02 09:31:56 +08:00
|
|
|
if transaction.is_dirty():
|
2013-02-06 05:52:29 +08:00
|
|
|
# Note: it is possible that the commit fails. If the reason is
|
|
|
|
# closed connection or some similar reason, then there is
|
|
|
|
# little hope to proceed nicely. However, in some cases (
|
|
|
|
# deferred foreign key checks for exampl) it is still possible
|
|
|
|
# to rollback().
|
|
|
|
try:
|
|
|
|
transaction.commit()
|
|
|
|
except Exception:
|
|
|
|
# If the rollback fails, the transaction state will be
|
|
|
|
# messed up. It doesn't matter, the connection will be set
|
|
|
|
# to clean state after the request finishes. And, we can't
|
|
|
|
# clean the state here properly even if we wanted to, the
|
|
|
|
# connection is in transaction but we can't rollback...
|
|
|
|
transaction.rollback()
|
|
|
|
transaction.leave_transaction_management()
|
|
|
|
raise
|
2006-05-02 09:31:56 +08:00
|
|
|
transaction.leave_transaction_management()
|
|
|
|
return response
|