123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- .. _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 run with an open transaction which it
- commits 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.
- .. _topics-db-transactions-autocommit:
- ``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
- Transactions and savepoints in PostgreSQL 8
- ===========================================
- When a call to a PostgreSQL 8 cursor raises an exception, all subsequent SQL
- in the same transaction fails with the error "current transaction is aborted,
- queries ignored until end of transaction block". Whilst simple use of save()
- is unlikely to raise an exception in PostgreSQL, there are many more advanced
- usage patterns which might: for example, saving objects with unique fields,
- saving using the force_insert/force_update flag, or invoking custom SQL.
- In any of these cases, you can wrap the command which may throw
- IntegrityError inside savepoints, which will then allow subsequent commands
- to proceed. Example::
- try:
- sid = transaction.savepoint()
- x.save()
- transaction.savepoint_commit(sid)
- except IntegrityError:
- transaction.savepoint_rollback(sid)
- raise
- Savepoints are not implemented in PostgreSQL 7. If you experience an
- IntegrityError when using PostgreSQL 7, you will need to rollback to the
- start of the transaction.
|