如何在Django中進行事務操作呢?
近期,公司里要使用Django開發一套金融相關的系統。
涉及錢了.....安全安全安全
如果錢轉到一半,系統崩了,咋辦?
如果錢匯到一半,系統崩了,咋辦?
如果東西買到一半,系統崩了,咋辦?
我錢轉到一半,錢已經從我的賬戶扣除了,但是,服務出問題了,當掉了,這條任務執行到一半停掉了,那我的錢呢???
這就會造成嚴重的損失?
怎么辦?
還記得在Mysql數據庫中的原子操作嗎?
不記得??!!!
好吧,我告訴你。
客戶A要給客戶B轉一筆錢,這個在數據庫中需要進行兩步:
1.客戶A減錢
2.客戶B加錢
如果在第一步結束后,服務器出現異常,停下了,第二步沒有進行,如果數據庫使用了事務操作,真的出現異常的時候,前面的操作會進行回滾。
簡單的說就是:要么全部執行成功,要么一個都不執行
這個回滾的操作就叫做數據庫的原子性操作。
但是啊,這是在MySQL數據庫中,我們在Django的ORM中如何進行呢?
首先,我們要導入一個Django的內置模塊
from django.db import transaction
接着,就可以使用了
from django.db import transaction with transaction.atomic(): //ORM操作 pass
我們舉個例子測試一下
1.創建一個項目,新建一個APP(基礎操作,這里不再贅述)
2.通過ORM創建生成表
from django.db import models class UserInfo(models.Model): username = models.CharField("用戶",max_length=32) balance = models.CharField("余額",max_length=32)
注意啊:踩過的坑,涉及金融計算,涉及小數啊,要求特別精確的,我們用字符串存儲。
如果是金融計算的話,我們用一個decimal來進行計算。
3.我們給數據庫加兩條數據,用來模擬兩個用戶之間的轉賬
4.配置URL
5.創建對應的視圖函數
from django.shortcuts import render,HttpResponse from app01 import models from django.db import transaction from django.db.models import F def index(request): try: with transaction.atomic(): models.UserInfo.object.filter(id=1).update(balance=F("balance")-100)
models.UserInfo.object.filter(id=2).update(balance=F("balance")+100) except Exception as e: return HttpResponse("出現錯誤<%s>"%str(e)) return HttpResponse("執行成功")
當我們訪問index的時候,會進行一次轉賬操作
6.現在,我們讓他報錯
from django.shortcuts import render,HttpResponse from app01 import models from django.db import transaction from django.db.models import F def index(request): try: with transaction.atomic(): models.UserInfo.object.filter(id=1).update(balance=F("balance")-100) raise 一個錯誤 models.UserInfo.object.filter(id=2).update(balance=F("balance")+100) except Exception as e: return HttpResponse("出現錯誤<%s>"%str(e)) return HttpResponse("執行成功")
我們再次查看數據庫文件,如果沒有數據的原子性操作,我們第一條sql執行完報錯,那錢肯定是減去了
但是,我們進行的是原子性的操作,你會發現錢沒有減誒。
完美,沒毛病
這是常規的一種操作,另外還有一起其他的方式
對整個view視圖開啟事務
from django.db import transaction @transaction.atomic def index(request): //ORM操作 return ....
注意:在原子塊中不要進行錯誤捕獲
當退出原子塊的時候,Django會去查看它是否正常退出或者是否有異常來確定是否提交或者回滾
如果你捕獲並處理了原子塊中的異常,可能會隱藏Django中發生問題的事實。這樣可能會造成非預期的行為。
