Django中的事務(Transaction)管理

轉自: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中間件會將置於其後的中間件都包含在事務的範圍之中(用於緩存的中間件除外,他們不受影響,例如CacheMiddlewareUpdateCacheMiddlewareFetchFromCacheMiddleware)。

另外需要注意的是,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官方文檔翻譯而來,參考資料是相關的文檔。如果要查看原文或是關於事務更多的細節(例如保存點),可以查閱。

 

參考資料:

Django官方文檔關於事務的說明


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章