from django_redis import get_redis_connection
class OrderCommitView(view):
@transaction.atomic
def post(self, request):
# 判断用户是否登录
user = request.user
if not user.is_authenticated():
return JsonResponse("res":0,"error_msg":"用户未登录")
addr_id = request.POST.get('addr_id')
pay_method = request.POST.get('pay_methon')
sku_ids = request.POST.get('sku_ids')
if not all([addr_id, pay_method, sku_ids]):
return JsonResponse({'res':1, 'error_msg':'params not enough'})
# 校验支付方式
if pay_method not in OrderInfo.PAY_METHODS.keys():
return JsonResponse('ret':2,'error_msg':'非法支付方式')
# 校验地址
try:
addr = Address.objects.get(id=addr_id)
except Address.DoesNotExist:
return JsonResponse('ret':3,'error_msg':"地址非法")
# 创建订单核心业务
订单id :日期加用户的id
order_id = datetime.now().strftime("%Y%m%d%H%M%S")+str(user.id)
# 运费
transit_price = 10
# 总数目总金额
total_count = 0
total_price = 0
# 设置事物保存点
save_id = transaction.savepoint()
try:
# todo 向df_oeder_info表中添加一条记录
order = OrderInfo.objects.create(order_id=order,user=user,pay_method=pay_method,total_count=total_count,total_price=total_price)
conn = get_redis_connection('default')
cart_key = 'cart_%d'%user.id
sku_ids = sku_ids.split(',')
for sku_id in sku_ids:
# 获取商品信息
# for 循环3次 尝试都能下单成功
for i in range(3):
try:
sku = GoodsSKU.objects.get(id=sku_id)
except:
# 商品不存在
transaction.savepoint_rollback(save_id)
return JsonResponse({'ret':4,'error_msg':"商品不存在"})
# 从redis中获取用户需要购买的商品的数量
count = conn.hget(cart_key,sku.stock)
# todo 判断商品的库存
if int(count) > sku.stock:
transaction.savepoint_rollback(save_id)
return JsonResponse({'res':6,'error_msg':'商品库存不足'})
# todo 更新商品的库存和销量
origin_stock = sku.stock
new_stock = origin_stock - int(count)
new_sales = sku.sales + int(count)
print('user:%s,stock:%s'%(user.id,sku.stock))
import time
time.sleep(10)
# upload df_goods_sku set stock=new_stock,sales=new_sales where id=sku_id and stock=origin_stock
#乐观锁 res返回受影响的行数
res = GoodsSKU.objects.filter(id=sku_id,stock=origin_stock).update(stock=new_stock.sales=new_sales)
if res == 0:
if i ==2:
transactin.savepoint_rollback(save_id)
return JsonResponse({'res':7,'error_msg':"下单失败2})
continue
# todo 向df_order_goods表中添加一条记录
OrderGoods.objects.create(order=order,
sku=sku,count=count,price=sku.price)
# todo 累加计算订单商品的总数量和总价格
amount = sku.price*int(count)
total_count += int(count)
total_price += amount
break
# todo更新订单信息表中的商品的总数量和总价格
order.total_count = total_count
order.total_price = total_price
order.save()
except Exception as e:
transaction.savepoint_rollback(save_id)
return JsonResponse('res':7,'error_msg':'下单失败')
# 提交事务
transaction.savepoint_commit(save_id)
# 提交事务
conn.hdel(cart_key,*sku_ids)
# 返回应答
return JsonResponse({'res':5,'message':'创建成功'})
最后一步:
乐观锁需要将数据库(MYSQL)的默认隔离程度可重复读(读的是第一次读到的数据),所以需要将MySQL的隔离级别更改为读已提交
打开MySQL的配置文件 sudo vi /etc/mysql/mysqlconf.d/
修改为读已提交
transaction_isolation = READ_COMMITTED
重启MySQL:sudo service mysql restart