写在前面:
默认情况下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到一个不存在的账号
----------------------------------------------------------------------------------------------