轉自:http://blog.sina.com.cn/s/blog_3fe961ae010167ah.html
Django默認的事務行爲
默認情況下,在Django中事務是自動提交的。當我們運行Django內置的模板修改函數時,例如調用model.save()或model.delete()時,事務將被立即提交。這種機制和數據庫的自動提交事務機制類似。記住這裏沒有默認的回滾機制。
在HTTP請求上加事務
對於Web請求,Django官方推薦使用中件間TransactionMiddleware來處理請求和響應中的事務。它的工作原理是這樣的:當一個請求到來時,Django開始一個事務,如果響應沒有出錯,Django提交這期間所有的事務,如果view中的函數拋出異常,那麼Django會回滾這之間的事務。
爲了實現這個特性,需要在MIDDLEWARE_CLASSES setting中添加TransactionMiddleware:
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
)
順序很重要,TransactionMiddleware中間件會將置於其後的中間件都包含在事務的範圍之中(用於緩存的中間件除外,他們不受影響,例如CacheMiddleware,UpdateCacheMiddleware和FetchFromCacheMiddleware)。
另外需要注意的是,TransactionMiddleware只會影響DATABASES設置中的默認的數據庫,對於其它的數據庫,如果我們實現事務控制的話只能用別的方案了。
在View中實現事務控制
如果想在更細粒度的條件下(例如在一個view函數中)控制事務,我們可以使用django.db.transaction。有兩種用法:
1.使用裝飾器
from django.db import transaction
@transaction.commit_on_success
def viewfunc(request):
# ...
# this code executes inside a transaction
# ...
2.使用context manager
from django.db import transaction
def viewfunc(request):
# ...
# this code executes using default transaction management
# ...
with transaction.commit_on_success():
# ...
# this code executes inside a transaction
# ...
這兩種方法都可以正常工作。不過如果使用的Python版本爲2.5並且要使用with語法的話,還需加一句
from __future__ import with_statement。
所以爲了最大的兼容性,下面的示例使用裝飾器來實現事務。
autocommit()
使用autocommit裝飾器可以將view函數中的事務還原成Django默認的自動提交模式,無視全局事務的設置。
示例:
from django.db import transaction
@transaction.autocommit
def viewfunc(request):
....
@transaction.autocommit(using="my_other_database")
def viewfunc2(request):
....
commit_on_success()
顧名思義,view函數成功則提交事務,否則回滾。用法同上。
commit_manually()
告訴Django我們將自己控制函數中的事務處理。並且要注意,如果在視圖函數中改變了數據庫的數據並且沒有調用commit() 或rollback(),那麼將拋出TransactionManagementError異常。
示例:
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()
@transaction.commit_manually(using="my_other_database")
def viewfunc2(request):
....
本文內容全部由Django官方文檔翻譯而來,參考資料是相關的文檔。如果要查看原文或是關於事務更多的細節(例如保存點),可以查閱。
參考資料: