class Creat(APIView): # 建立订单 @transaction.atomic # 开启事务 def post(self,request): param=request.data order_obj=OrderForm(request.data) host_ip=request.get_host() goods_list=param.get("buy_list") #这个的goods_list,就是用户下单的商品以及数量 #数据格式{"2":2,"1":2} if order_obj.is_valid() and goods_list: open_id=function.check_login_key(param['token']) if not open_id: return Response({"code":200,"msg":"token不对"}) user=models.Wxuser.objects.filter(openid=open_id).first() # 组织订单的信息 order_data={"consignee_mobile":param['phone'],'consignee_name':param['name'],'wxuser_id':user.id,\ "memo":param['remark'],"consignee_address":f"{param['province']},{param['city']},{param['county']}",\ } order_data['order_id']=function.get_order_id() order_data['order_total']=0 order_data['quantity']=0 goods_list_id = list(goods_list.keys()) #这里是全部商品的信息 all_good_info=models.Product.objects.filter(product_id__in=goods_list_id) sid=transaction.savepoint() # 建立一个保存点,当数据库出现错误时,能够返回到当前状态 for goods in all_good_info: goods.product_id = str(goods.product_id) order_data["order_total"]+=goods.price*goods_list[goods.product_id] order_data['quantity']+=goods_list[goods.product_id] for i in range(3): stock=goods.stock.quantity # 点的时候仍是在查数据库,拿到最新的数据 new_quantity=stock-goods_list[goods.product_id] #判断库存是否够 if new_quantity < 1: transaction.savepoint_rollback(sid) # 在必定条件下,事务回滚到保存点 return Response({ "code": 200, 'msg': "库存不足" }) buy_count=goods.buy_count+goods_list[goods.product_id] res=models.Stock.objects.filter(quantity=stock,stock_id=goods.stock.stock_id).update(quantity=new_quantity) if res==0: if i==2: # 多循环几回,尽可能操做成功 transaction.savepoint_rollback(sid) return Response({"code":200,"msg":"下单失败"}) continue else: break order_item_data = {'order_id': order_data['order_id'], 'product_id': goods.product_id, \ "name": goods.name, "image": goods.image, "price": goods.price, \ "nums": goods_list[goods.product_id], "brief": goods.brief} models.Order_items.objects.create(**order_item_data) # 建立子订单 models.Product.objects.filter(product_id=goods.product_id).update(buy_count=buy_count) 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['ip']=host_ip.split(":")[0] order_data['open_id']=open_id data=pay_class().pay(order_data) transaction.savepoint_commit(sid) #提交一个celery任务检查订单 function.add_task(order_data['order_id']) return Response({"code":0,"msg":"成功","data":data}) except: transaction.savepoint_rollback(sid) return Response({"code":200,"msg":"未知的支付方式"}) else: return Response({"code":200,"msg":"数据错误"}) from datetime import datetime from app01.tasks import del_order def add_task(order_id,how_time=0): ctime = datetime.now() utc_ctime = datetime.utcfromtimestamp(ctime.timestamp()) from datetime import timedelta time_delay = timedelta(seconds=900) # time_delay = timedelta(seconds=how_time) # 传过来的时间去肯定多久执行一次,而非固定时间,更加人性化 task_time = utc_ctime + time_delay result = del_order.apply_async(args=[order_id, ], eta=task_time) print(result) @task @transaction.atomic def del_order(order_id): #把他看成一个脚本,若是要用的话,我就要启动django BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # 定位到你的django根目录 sys.path.append(os.path.abspath(BASE_DIR)) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "py8api.settings") django.setup() from app01 import models #检查该订单是否被支付, order_data=models.Order.objects.filter(order_id=order_id,pay_status=0,status="active") #若是没有被支付 if order_data: #获取该订单的全部子订单中的商品和商品的数量 order_items=models.Order_items.objects.filter(order_id=order_id).values('product','nums') #将查出来的商品和数量作成字典:{product_id:nums} goods_list= {item['product']:item['nums'] for item in order_items} #获取全部的商品的id goods_list_id=list(goods_list.keys()) #获取全部的商品 all_goods_info = models.Product.objects.filter(product_id__in=goods_list_id) #开启事务 sid = transaction.savepoint() #循环处理。全部的商品 for goods in all_goods_info: # 若是下单成功后的库存 for i in range(3): new_quantity = goods.stock.quantity + goods_list[goods.product_id] buy_count = goods.buy_count - goods_list[goods.product_id] res = models.Stock.objects.filter(quantity=goods.stock.quantity, stock_id=goods.stock.stock_id).update( quantity=new_quantity) if res == 0: if i == 2: # 回滚 transaction.savepoint_rollback(sid) #可是还要继续提交任务取消订单 from app01.comment import function function.add_taks(order_id) return continue else: models.Product.objects.filter(product_id=goods.product_id).update(buy_count=buy_count) break res= models.Order.objects.filter(order_id=order_id, pay_status=0,status="active").update(status="dead") if res ==0 : #订单恰好付款了 transaction.savepoint_rollback(sid) transaction.savepoint_commit(sid)