订单部分
基本功能:提交订单、保存订单
创建订单数据表,分为两个表,一个订单基本信息表,一个订单商品表
订单结算
get 请求
- 用户点击去结算,跳转到提交订单页面
- 同时向后端发送请求
- 后端从 redis 数据库中查询出已勾选的 sku_id,查询出对应的商品信息
- 还需要添加上运费,在这里运费是写死的,没有进行计算,这个都好说,运费字段要使用 python 自带的 decimal 库中的 Decamal 类,这样数字才不会被进行约等于,而是输入多少就是多少
- 将数据进行序列化然后返回
- 最后在前端进行展示,并计算好金钱,前端在请求时还会在请求一下地址来让用户进行勾选,可以选择支付方式
保存订单
post 请求 参数是 地址 和 支付方式, 后端生成订单编号,保存并返回
这里是需要进行创建,视图继承自 CreateAPIView 类,在序列化器中重写 create 方法进行创建即可
-
create 流程
-
获取当前下单用户,context[‘request’].user,在序列化器中,context 中会包含 request 对象,从中获取就行
-
生成订单编号,使用当前时间加上用户 id 的方式来生成
-
在序列化器中校验过的数据就可以使用 validated_data 来取得地址和支付方式
-
生成订单,考虑到要同时操作三张表 OrderInfo 表、SKU 表、OrderGoods,所以就需要开启事务
-
使用
with transaction.atomic():
开启一个事务 -
创建一个保存点,方便出现错误时进行回退,
save_id = transaction.savepoint()
-
创建订单信息,将对应的字段填充进去
-
从 redis 中查询出要结算的购物车数据,取出所有要结算的商品 id
-
遍历商品 id,在这里考虑到了商品并发下单问题,这里使用乐观锁来解决,就是在循环中,每次都进行查询,在更新的时候再次进行查询,判断一下商品数量是否和第一次查询的一样,不一样就跳过,只有一样才能更新成功,就像电商常用的秒杀一样,看着在下单界面,但是一直转圈,转了半天来了一句库存不足,大概就是这个原因吧
-
查询出当前的商品对象,取出要结算的当前商品的数量,保存一下当前库存
-
判断一下库存,如果不足直接退回到保存点
transaction.savepoint_rollback(save_id)
,并抛出错误 -
库存充足,需要进行库存和销量的更新,更新时需要再次进行查询,条件是最开始查询出的库存等于当前库存,这样才能更新成功
SKU.object.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=origin_sales)
-
更新商品销量的信息
-
更新订单的总数和总金额
-
保存订单商品,插入对应的数据,执行完结束当前循环
-
给金额加上运费
-
添加上异常捕获,一个是
serializers.ValidationError
,这个异常自己进行了回滚;还有就是其他异常的捕获,就需要自己进行异常的捕获 -
当所有的执行完毕,将事务进行提交,这样数据库更新才完成
-
最后从 redis 中删除已结算的商品数据
-
订单保存完毕跳转到下单成功页面,根据用户选择的付款方式进行展示