在完成了前一小节的数据库事务,提交订单的视图类就可以直接继承 mixin 类。
① 创建事务保存点
# 创建事务保存点
save_id = transaction.savepoint()
try:
order = OrderInfo.objects.create(
order_id=order_id,
user=user,
address=address,
total_amount=0,
trans_cost=10,
pay_method=pay_method,
)
② 回退的保存点的状态
# 回退的保存点的状态
transaction.savepoint_rollback(save_id)
③ 提交订单
class CommitOrderView(LoginRequiredJsonMixin, TransactionAtomicMixin, View):
"""提交订单"""
def post(self, request):
# 获取参数
# user 地址id 支付方式 商品id 数量(从购物车中获取)
user = request.user
address_id = request.POST.get("address_id")
sku_ids = request.POST.get("sku_ids") # "1,2,3,4"
pay_method = request.POST.get("pay_method")
# 校验参数
if not all([address_id, sku_ids, pay_method]):
return JsonResponse({"code": 2, "message": "参数缺失"})
# 判断地址是否存在
try:
address = Address.objects.get(id=address_id)
except Address.DoesNotExist:
return JsonResponse({"code": 3, "message": "地址不存在"})
# 判断支付方式
pay_method = int(pay_method)
if pay_method not in OrderInfo.PAY_METHODS.keys():
return JsonResponse({"code": 4, "message": "支付方式错误"})
# 判断商品
sku_ids = sku_ids.split(",") # ["1", "2"]
redis_conn = get_redis_connection("default")
cart = redis_conn.hgetall("cart_%s" % user.id)
# 创建一个订单基本信息表数据
# 自定义的order_id "20171026111111用户id"
order_id = timezone.now().strftime("%Y%m%d%H%M%S") + str(user.id)
# 创建事务保存点
save_id = transaction.savepoint()
try:
order = OrderInfo.objects.create(
order_id=order_id,
user=user,
address=address,
total_amount=0,
trans_cost=10,
pay_method=pay_method,
)
total_count = 0 # 总数
total_amount = 0 # 总金额
for sku_id in sku_ids:
for i in range(3):
try:
sku = GoodsSKU.objects.get(id=sku_id)
except GoodsSKU.DoesNotExist:
# 回退的保存点的状态
transaction.savepoint_rollback(save_id)
return JsonResponse({"code": 5, "message": "商品有误"})
# 获取订购的商品数量,判断库存
sku_count = cart.get(sku_id.encode())
sku_count = int(sku_count)
if sku_count > sku.stock:
# 回退的保存点的状态
transaction.savepoint_rollback(save_id)
return JsonResponse({"code": 6, "message": "库存不足"})
# 减少商品的库存, 增加商品的销量
origin_stock = sku.stock
new_stock = origin_stock - sku_count
new_sales = sku.sales + sku_count
# update操作会返回受影响的行数,即更新成功的函数
result = GoodsSKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
if result == 0 and i < 2:
# 表示更新失败
continue
elif result == 0 and i == 2:
# 表示尝试三次失败
transaction.savepoint_rollback(save_id)
return JsonResponse({"code": 7, "message": "下单失败"})
# 保存订单商品
OrderGoods.objects.create(
order=order,
sku=sku,
count=sku_count,
price=sku.price,
)
# 累计计算总数
total_count += sku_count
# 累计计算总金额
total_amount += (sku.price * sku_count)
# 跳出三次循环,处理下一个商品
break
# 修改订单基本信息表中的统计数据字段
order.total_count = total_count
order.total_amount = total_amount + 10
order.save()
except Exception:
# 出现任何异常,都要回退的保存点的状态
transaction.savepoint_rollback(save_id)
return JsonResponse({"code": 8, "message": "下单失败"})
# 执行成功,提交事务
transaction.savepoint_commit(save_id)
# 保存最新的购物车数据
redis_conn.hdel("cart_%s" % user.id, *sku_ids) # 删除订购的商品
# 返回前端json状态
return JsonResponse({"code": 0, "message": "创建订单成功"})