django后台使用MySQL情况下的事务控制详解
写在前面:
默认情况下django会把autocommit设置为“1”也就是说所针对数据库的每一次操作都会被做成“单独”的一个事务;这样的处理好处就在于它方便,
在编程的时候可以少写一些代码,比如我们不用先“start transaction ” 操作完之后再“commit” 或 “rollback”。
django对事务控制的实现方式:
django中通过transaction.atomic()上下文来完成事务控制
try: with transaction.atomic(): # 对数据库的操作 except Exception as e: # 异常处理 #其它处理逻辑
以学院式的银行转账业务为例:
1):一张表示银行存款的表(为了突出事务控制在些不对表进行过多的设计)
from django.db import models # Create your models here. class SavingCard(models.Model): name=models.CharField(max_length=64,default='',null=False) saving = models.DecimalField(max_digits=16,decimal_places=4,default=0,null=False)
以上模型它所对应的SQL语句如下
CREATE TABLE `bank_savingcard` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `saving` decimal(16,4) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
手工在数据库中插入两行测试数据
insert into bank_savingcard(name,saving) values ('jianglexing',100),('welson',80);
2):用django实现一个转账功能的view
from django.shortcuts import render from .models import SavingCard from django.db import transaction from django.http import HttpResponse # Create your views here. def transfer(request,fromname,toname,count): """ 完整的转账功能 """ try: with transaction.atomic(): if count < 0: raise ValueError("转账资金不得小于0元") fromAccount = SavingCard.objects.get(name=fromname) toAccount = SavingCard.objects.get(name=toname) if count > fromAccount.saving: raise ValueError("转账资金不得大于卡内余额") fromAccount.saving=fromAccount.saving-count toAccount.saving = toAccount.saving + count fromAccount.save() toAccount.save() except Exception as e: return HttpResponse("<p>{} {}</p>".format("出现异常转账失败",e)) return HttpResponse("转账成功")
注册转账接口
from django.contrib import admin from django.urls import path from bank.views import transfer urlpatterns = [ path('admin/', admin.site.urls), path('bank/<str:fromname>/transaction/<str:toname>/<int:count>/',transfer) ]
3):调用转账接口
http://127.0.0.1:8080/bank/jianglexing/transaction/welson/5/
jianglexing转5元给welson
4):转账前后数据库的内容变化
select * from bank_savingcard; +----+-------------+----------+ | id | name | saving | +----+-------------+----------+ | 1 | jianglexing | 100.0000 | | 2 | welson | 80.0000 | +----+-------------+----------+ 2 rows in set (0.00 sec) select * from bank_savingcard; +----+-------------+---------+ | id | name | saving | +----+-------------+---------+ | 1 | jianglexing | 95.0000 | | 2 | welson | 85.0000 | +----+-------------+---------+ 2 rows in set (0.00 sec)
5):强行转账1000元看一下
http://127.0.0.1:8080/bank/jianglexing/transaction/welson/1000/
前后的数据库内容对比
select * from bank_savingcard; +----+-------------+---------+ | id | name | saving | +----+-------------+---------+ | 1 | jianglexing | 95.0000 | | 2 | welson | 85.0000 | +----+-------------+---------+ 2 rows in set (0.00 sec) select * from bank_savingcard; +----+-------------+---------+ | id | name | saving | +----+-------------+---------+ | 1 | jianglexing | 95.0000 | | 2 | welson | 85.0000 | +----+-------------+---------+ 2 rows in set (0.00 sec)
6):强行转账1000到一个不存在的账号
----------------------------------------------------------------------------------------------