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)