You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
6.2 KiB
165 lines
6.2 KiB
.. _topics-db-transactions: |
|
|
|
============================== |
|
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/doc/refman/5.0/en/sql-syntax-transactions.html
|
|
|