diff --git a/django/db/transaction.py b/django/db/transaction.py index 9af5b4e5ab..3419c01257 100644 --- a/django/db/transaction.py +++ b/django/db/transaction.py @@ -18,11 +18,11 @@ from django.conf import settings class TransactionManagementError(Exception): """ - This is the exception that is thrown when - something bad happens with transaction management. + This exception is thrown when something bad happens with transaction + management. """ pass - + # The state is a dictionary of lists. The key to the dict is the current # thread and the list is handled as a stack of values. state = {} @@ -37,9 +37,9 @@ def enter_transaction_management(): Enters transaction management for a running thread. It must be balanced with the appropriate leave_transaction_management call, since the actual state is managed as a stack. - - The state and dirty flag are carried over from the surrounding block or - from the settings, if there is no surrounding block (dirty is allways false + + The state and dirty flag are carried over from the surrounding block or + from the settings, if there is no surrounding block (dirty is always false when no current block is running). """ thread_ident = thread.get_ident() @@ -55,7 +55,7 @@ def leave_transaction_management(): """ Leaves transaction management for a running thread. A dirty flag is carried over to the surrounding block, as a commit will commit all changes, even - those from outside (commits are on connection level). + those from outside. (Commits are on connection level.) """ thread_ident = thread.get_ident() if state.has_key(thread_ident) and state[thread_ident]: @@ -63,14 +63,14 @@ def leave_transaction_management(): else: raise TransactionManagementError("This code isn't under transaction management") if dirty.get(thread_ident, False): - # I fixed it for you this time, but don't do it again! rollback() raise TransactionManagementError("Transaction managed block ended with pending COMMIT/ROLLBACK") dirty[thread_ident] = False def is_dirty(): """ - Checks if the current transaction requires a commit for changes to happen. + Returns True if the current transaction requires a commit for changes to + happen. """ return dirty.get(thread.get_ident(), False) @@ -89,8 +89,8 @@ def set_dirty(): def set_clean(): """ Resets a dirty flag for the current thread and code streak. This can be used - to decide in a managed block of code to decide whether there should happen a - commit or rollback. + to decide in a managed block of code to decide whether a commit or rollback + should happen. """ thread_ident = thread.get_ident() if dirty.has_key(thread_ident): @@ -110,7 +110,7 @@ def is_managed(): def managed(flag=True): """ - Puts the transaction manager into a manual state - managed transactions have + Puts the transaction manager into a manual state: managed transactions have to be committed explicitely by the user. If you switch off transaction management and there is a pending commit/rollback, the data will be commited. @@ -163,11 +163,10 @@ def rollback(): def autocommit(func): """ - Decorator that activates commit on save. This is Django's default behavour; + Decorator that activates commit on save. This is Django's default behavior; this decorator is useful if you globally activated transaction management in - your settings file and want the default behaviour in some view functions. + your settings file and want the default behavior in some view functions. """ - def _autocommit(*args, **kw): try: enter_transaction_management() @@ -175,17 +174,15 @@ def autocommit(func): return func(*args, **kw) finally: leave_transaction_management() - return _autocommit def commit_on_success(func): """ - This decorator activates commit on response. This way if the viewfunction - runs successfully, a commit is made, if the viewfunc produces an exception, + This decorator activates commit on response. This way, if the view function + runs successfully, a commit is made; if the viewfunc produces an exception, a rollback is made. This is one of the most common ways to do transaction control in web apps. """ - def _commit_on_success(*args, **kw): try: enter_transaction_management() @@ -202,16 +199,15 @@ def commit_on_success(func): return res finally: leave_transaction_management() - return _commit_on_success def commit_manually(func): """ Decorator that activates manual transaction control. It just disables - automatic transaction control and doesn't do any commit/rollback of it's own - - it's up to the user to call the commit and rollback functions themselves. + automatic transaction control and doesn't do any commit/rollback of its + own -- it's up to the user to call the commit and rollback functions + themselves. """ - def _commit_manually(*args, **kw): try: enter_transaction_management() @@ -221,5 +217,3 @@ def commit_manually(func): leave_transaction_management() return _commit_manually - - diff --git a/django/middleware/transaction.py b/django/middleware/transaction.py index aa35cc1d2d..da218ac31a 100644 --- a/django/middleware/transaction.py +++ b/django/middleware/transaction.py @@ -5,10 +5,9 @@ class TransactionMiddleware: """ 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 successfull response is created. If an + commit, the commit is done when a successful response is created. If an exception happens, the database is rolled back. """ - def process_request(self, request): """Enters transaction management""" transaction.enter_transaction_management() @@ -26,4 +25,4 @@ class TransactionMiddleware: if transaction.is_dirty(): transaction.commit() transaction.leave_transaction_management() - return response \ No newline at end of file + return response diff --git a/docs/transactions.txt b/docs/transactions.txt index 23f2b095e5..c75efb83b9 100644 --- a/docs/transactions.txt +++ b/docs/transactions.txt @@ -8,7 +8,7 @@ Django's default transaction behavior ===================================== The default behavior of Django is to commit on special model functions. If you -call ``model.save()`` or ``model.delete()``, that change will be committed immediately. +call ``model.save()`` or ``model.delete()``, that change will be committed immediately. This is much like the auto-commit setting for most databases: as soon as you perform an action that needs to write to the database, Django produces the @@ -19,7 +19,7 @@ Tying transactions to HTTP requests =================================== A useful way to handle transactions is to tie them to the request and response -phases. +phases. When a request starts, you start a transaction. If the response is produced without problems, any transactions are committed. If the view function produces @@ -39,17 +39,17 @@ only for the view functions called, but for all middleware modules that come after it. So if you use the session middleware after the transaction middleware, session creation will be part of the transaction. -The cache middleware isn't affected as it uses it's own database cursor (that is -mapped to it's own database connection internally) and only the database based -cache is affected. +The cache middleware isn't affected, as it uses its own database cursor (which +is mapped to its own database connection internally), and only the +database-based cache is affected. Controlling transaction management in views =========================================== -For many people, implicit request-based transactions will work wonderfully. -However, if you need to control the way that transactions are managed, -there are a set of decorators that you can apply to a function to change -the way transactions are handled. +For many people, implicit request-based transactions will work wonderfully. +However, if you need to control the way that transactions are managed, +you can use decorators that you can apply to a function to change the way +transactions are handled. .. note:: @@ -64,19 +64,19 @@ default commit behavior of Django, regardless of the global setting. Just use the decorator like this:: from django.db.transaction import autocommit - + @transaction.autocommit def viewfunc(request): .... -Within ``viewfunc`` transactions will be comitted as soon as you call -``model.save()``, ``model.delete()``, or any similar function that writes to the +Within ``viewfunc`` transactions will be committed as soon as you call +``model.save()``, ``model.delete()``, or any other function that writes to the database. ``commit_on_success`` --------------------- -You can use the ``commit_on_success`` decorator to use a single transaction for +You can use the ``commit_on_success`` decorator to use a single transaction for all the work done in a function:: from django.db.transaction import commit_on_success @@ -85,7 +85,7 @@ all the work done in a function:: def viewfunc(request): .... -If the function returns successfully then all work done will be committed. If an +If the function returns successfully, then all work done will be committed. If an exception is raised beyond the function, however, the transaction will be rolled back. @@ -93,10 +93,12 @@ back. ------------------- Sometimes you need full control over your transactions. In that case, you can use the -``commit_manually`` decorator which will make you run your own transaction management. +``commit_manually`` decorator, which tells Django you'll be managing the transaction +on your own. -If you don't commit or rollback and did change data (so that the current transaction -is marked as dirty), you will get a ``TransactionManagementError`` exception saying so. +If you don't commit or rollback and did change data (so that the current +transaction is marked as dirty), you'll get a ``TransactionManagementError`` +exception. Manual transaction management looks like:: @@ -106,9 +108,9 @@ Manual transaction management looks like:: def viewfunc(request): ... # You can commit/rollback however and whenever you want - transaction.commit() + transaction.commit() ... - + # But you've got to remember to do it yourself! try: ... @@ -117,8 +119,8 @@ Manual transaction management looks like:: else: transaction.commit() -..admonition:: An important note to users of earlier django releases: - +..admonition:: An important note to users of earlier Django releases: + The database ``connection.commit`` and ``connection.rollback`` functions (also called ``db.commit`` and ``db.rollback`` in 0.91 and earlier), no longer exist and have been replaced by the ``transaction.commit`` and @@ -128,7 +130,7 @@ How to globally deactivate transaction management ================================================= Control freaks can totally disable all transaction management by setting -``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in your settings file. +``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in the Django settings file. If you do this, there will be no management whatsoever. The middleware will no longer implicitly commit transactions, and you'll need to roll management @@ -136,6 +138,6 @@ yourself. This even will require you to commit changes done by middleware somewhere else. Thus, this is best used in situations where you want to run your own transaction -controlling middleware or do something really strange. In almost all situations +controlling middleware or do something really strange. In almost all situations, you'll be better off using the default behavior or the transaction middleware -and only modify selected functions as needed. \ No newline at end of file +and only modify selected functions as needed.