| ============================== |
| Managing database transactions |
| ============================== |
| |
| Django gives you a few ways to control how database transactions are managed, |
| if you're using a database that supports transactions. |
| |
| Django's default transaction behavior |
| ===================================== |
| |
| Django's default behavior is to commit automatically when any built-in, |
| data-altering model function is called. For example, if you call |
| ``model.save()`` or ``model.delete()``, the 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 |
| ``INSERT``/``UPDATE``/``DELETE`` statements and then does the ``COMMIT``. |
| There's no implicit ``ROLLBACK``. |
| |
| Tying transactions to HTTP requests |
| =================================== |
| |
| The recommended way to handle transactions in Web requests is to tie them to |
| the request and response phases via Django's ``TransactionMiddleware``. |
| |
| It works like this: When a request starts, Django starts a transaction. If the |
| response is produced without problems, Django commits any pending transactions. |
| If the view function produces an exception, Django rolls back any pending |
| transactions. |
| |
| To activate this feature, just add the ``TransactionMiddleware`` middleware to |
| your ``MIDDLEWARE_CLASSES`` setting:: |
| |
| MIDDLEWARE_CLASSES = ( |
| 'django.contrib.sessions.middleware.SessionMiddleware', |
| 'django.middleware.common.CommonMiddleware', |
| 'django.middleware.cache.CacheMiddleware', |
| 'django.middleware.transaction.TransactionMiddleware', |
| ) |
| |
| The order is quite important. The transaction middleware applies not only to |
| view functions, but also 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. |
| |
| An exception is ``CacheMiddleware``, which is never affected. The cache |
| middleware uses its own database cursor (which is mapped to its own database |
| connection internally). |
| |
| Controlling transaction management in views |
| =========================================== |
| |
| For most people, implicit request-based transactions work wonderfully. However, |
| if you need more fine-grained control over how transactions are managed, you |
| can use Python decorators to change the way transactions are handled by a |
| particular view function. |
| |
| .. note:: |
| |
| Although the examples below use view functions as examples, these |
| decorators can be applied to non-view functions as well. |
| |
| ``django.db.transaction.autocommit`` |
| ------------------------------------ |
| |
| Use the ``autocommit`` decorator to switch a view function to Django's default |
| commit behavior, regardless of the global transaction setting. |
| |
| Example:: |
| |
| from django.db import transaction |
| |
| @transaction.autocommit |
| def viewfunc(request): |
| .... |
| |
| Within ``viewfunc()``, transactions will be committed as soon as you call |
| ``model.save()``, ``model.delete()``, or any other function that writes to the |
| database. |
| |
| ``django.db.transaction.commit_on_success`` |
| ------------------------------------------- |
| |
| Use the ``commit_on_success`` decorator to use a single transaction for |
| all the work done in a function:: |
| |
| from django.db import transaction |
| |
| @transaction.commit_on_success |
| def viewfunc(request): |
| .... |
| |
| If the function returns successfully, then Django will commit all work done |
| within the function at that point. If the function raises an exception, though, |
| Django will roll back the transaction. |
| |
| ``django.db.transaction.commit_manually`` |
| ----------------------------------------- |
| |
| Use the ``commit_manually`` decorator if you need full control over |
| transactions. It tells Django you'll be managing the transaction on your own. |
| |
| If your view changes data and doesn't ``commit()`` or ``rollback()``, Django |
| will raise a ``TransactionManagementError`` exception. |
| |
| Manual transaction management looks like this:: |
| |
| from django.db import transaction |
| |
| @transaction.commit_manually |
| def viewfunc(request): |
| ... |
| # You can commit/rollback however and whenever you want |
| transaction.commit() |
| ... |
| |
| # But you've got to remember to do it yourself! |
| try: |
| ... |
| except: |
| transaction.rollback() |
| else: |
| transaction.commit() |
| |
| .. admonition:: An important note to users of earlier Django releases: |
| |
| The database ``connection.commit()`` and ``connection.rollback()`` methods |
| (called ``db.commit()`` and ``db.rollback()`` in 0.91 and earlier) no longer |
| exist. They've been replaced by ``transaction.commit()`` and |
| ``transaction.rollback()``. |
| |
| How to globally deactivate transaction management |
| ================================================= |
| |
| Control freaks can totally disable all transaction management by setting |
| ``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in the Django settings file. |
| |
| If you do this, Django won't provide any automatic transaction management |
| whatsoever. Middleware will no longer implicitly commit transactions, and |
| you'll need to roll management yourself. This even requires 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, you'll be better off using the default behavior, or the |
| transaction middleware, and only modify selected functions as needed. |
| |
| Transactions in MySQL |
| ===================== |
| |
| If you're using MySQL, your tables may or may not support transactions; it |
| depends on your MySQL version and the table types you're using. (By |
| "table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction |
| peculiarities are outside the scope of this article, but the MySQL site has |
| `information on MySQL transactions`_. |
| |
| If your MySQL setup does *not* support transactions, then Django will function |
| in auto-commit mode: Statements will be executed and committed as soon as |
| they're called. If your MySQL setup *does* support transactions, Django will |
| handle transactions as explained in this document. |
| |
| .. _information on MySQL transactions: http://dev.mysql.com/books/mysqlpress/mysql-tutorial/ch10.html |