Django 事物
目录
Django 事物是什么
Djnago 如何使用事务
Djnago 如何使用事务
1. 给一个Http请求绑定事务(全局事物)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day59', 'USER': 'root', 'PASSWORD': '123', "POST": '127.0.0.1', 'PORT': 3306, 'ATOMIC_REQUESTS': True, # 设置为True代表同一个http请求所对应的所有SQL放在一个事物中执行 # (要么同时成功,要么同时失败), 这是全局性的配置, 如果要对某个 # http请求放水(然后自定义事物), 可以用non_atomic_requests修饰器 'OPTIONS': { "init_command": "SET storage_engine=INNODB", # 设置创建表的存储引擎 } } }
1.1 设置全局之后取消某个函数的事务,在视图函数添加装饰器@transaction.non_atomic_requests,则该视图不在事物之内。
from django.db import transaction class xxx(xxxView): @transaction.non_atomic_requests def post(self, request, *args, **kwargs): pass # 关闭其他除自己之外 @transaction.non_atomic_requests(using='other') def my_other_view(request): do_stuff_on_the_other_database()
2.显式地控制事务(局部事物)
原子性是数据库事务的一个属性。使用atomic,我们就可以创建一个具备原子性的代码块。一旦代码块正常运行完毕,
所有的修改会被提交到数据库。反之,如果有异常,更改会被回滚。
被atomic管理起来的代码块还可以内嵌到方法中。这样的话,即便内部代码块正常运行,如果外部代码块抛出异常的话,
它也没有办法把它的修改提交到数据库中。
2.1 atomic 提供两种方案实现事务:
2.1.1 atomic可以被当成装饰器使用
from django.db import transaction @transaction.atomic def viewfunc(request): # This code executes inside a transaction. do_stuff()
实例:
进入最外层atomic代码块时开启一个事务;
进入内部atomic代码块时创建保存点;
退出内部atomic时释放或回滚事务;
退出最外层atomic代码块时提交或者回滚事务;
"""创建订单"""
class Creat(APIView):
@transaction.atomic
def post(self,request):
param=request.data
form_obj=OrderForm(param)
if form_obj.is_valid() and param['buy_list']:
if request.META.get("HTTP_X_FORWARDED_FOR"):
host_ip = request.META["HTTP_X_FROWARDED_FOR"]
else:
host_ip = request.META["REMOTE_ADDR"]
user_cache=cache.get(param['token'])
if user_cache:
openid=user_cache.split("&")[0]
user_data=models.WxUser.objects.filter(openid=openid).first()
order_data = {"consignee_mobile": param['phone'],
'consignee_name': param['name'],
'wxuser_id': user_data.id,
"memo": param['remark'],
"consignee_area":f"{param['province']},{param['city']},{param['county']}",
"consignee_address":param['address'] ,
}
buy_list=param['buy_list']
goods_key=list(buy_list.keys())
all_product=models.Product.objects.filter(product_id__in=goods_key)
order_data['order_id']=func.get_order_id()
order_data['order_total']=0
order_data['quantity']=0
#开启库存
sid=transaction.savepoint()
for product in all_product:
product.product_id=str(product.product_id)
order_data['order_total']+=product.price*buy_list[product.product_id]
order_data['quantity']+=buy_list[product.product_id]
#创建子订单
for i in range(3):
#查询当前库存
stock=product.stock.quantity
#当前减轻购买的数量,等于剩余的库存
new_stock=stock-buy_list[product.product_id]
#判断库存是否足够
if new_stock<0:
#回滚
transaction.savepoint_rollback(sid)
#如果库存不住够,我们直接返回
return Response({"code":203,"msg":f"{product.name}库存不足"})
res=models.Stock.objects.filter(quantity=stock,stock_id=product.stock.stock_id).update(quantity=new_stock)
if not res:
if i==2:
transaction.savepoint_rollback(sid)
return Response({"code": 203, "msg": f"创建订单失败"})
else:
continue
else:
break
new_buy_count = product.buy_count + buy_list[product.product_id]
models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
order_item_data={'order_id': order_data['order_id'], 'product_id': product.product_id,
"name": product.name, "image": product.image, "price": product.price,
"nums": buy_list[product.product_id], "brief": product.brief}
models.Order_items.objects.create(**order_item_data)
models.Order.objects.create(**order_data)
pay_methon="Wxpay"
try:
pay_file=importlib.import_module(f"app01.Pay.{pay_methon}")
pay_class=getattr(pay_file,pay_methon)
order_data['open_id'] = openid
order_data['ip']=host_ip
data=pay_class().pay(order_data)
except:
transaction.savepoint_rollback(sid)
return Response({"code": 200, "msg": "未知的支付方式" })
transaction.savepoint_commit(sid)
func.add_task(order_data['order_id'])
return Response({"code": 200, "msg": "ok" ,"data":data})
else:
return Response({"code":202,"msg":"token已过期"})
else:
return Response({"code":201,"msg":"缺少参数"})
2.1.2 下面是被当做上下文管理器来使用
from django.db import transaction
def viewfunc(request):
# This code executes in autocommit mode (Django's default).
do_stuff()
with transaction.atomic():
# This code executes inside a transaction.
do_more_stuff()
实例:
from django.db import transaction
with transaction.atomic():
# 这部分代码会在事务中执行
# 创建保存点
save_id = transaction.savepoint()
try:
....
except:
# 回滚到保存点
transaction.savepoint_rollback(save_id)
# 提交从保存点到当前状态的所有数据库事务操作
transaction.savepoint_commit(save_id)

浙公网安备 33010602011771号