首先理解一下购物车和订单之间的关系。
我们现在是做了一种最简单的实现就是把购物车中所有商品进行一起的结算
orderInfo model 里面有一个order_sn是不能为空的。
点击去结算之后为它生成一个订单。然后让用户去支付页面进行支付。
如果用到viewset中的create mixin。会对这些字段进行验证。
但是用户是不可能post order_sn过来的。
那我们在model中设置该字段可以为空,这样验证字段时就没有问题了。
为什么不指向一个外键而是将值存起来呢?
因为用户有可能地址变动,将该地址删除了,但是地址相关联的订单作为历史数据不应该被改变。
orderInfo 只有基本的信息,但是与订单相关的还有订单的商品信息。
所以我们设计了 OrderGoods 来保存订单的商品。
添加一个OrderViewSet来实现订单接口
class OrderViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
"""
订单管理
list: 列出个人订单
create: 添加个人订单
delete: 删除个人订单
"""
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
serializer_class = OrderSerializer
def get_queryset(self):
return OrderInfo.objects.filter(user=self.request.user)
为什么使用genericViewset,而不是ModelViewset。因为订单一般是不允许被修改的。没有update这个mixin
在 Serializers.py 中添加一个 OrderSerializer
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = OrderInfo
fields = "__all__"
提交订单的时候不会再提交每个商品,因为逻辑是一种比较简单的业务逻辑,直接清空购物车
将购物车中的数据添加到 OrderGoods 中。
清空购物车数据
它在create订单的时候还多了两步
我们可以在 perform_create 中写,实际默认调用的是 Serializer 的save方法
views/OrderViewSet
def perform_create(self, serializer):
order = serializer.save()
save之前订单号是必须要有的,在Serializer中。
def generate_order_sn(self):
# 当前时间 + user.id + 随机数
from random import Random
random_ins = Random()
order_sn = "{time_str}{userid}{ranstr}".format(time_str=time.strftime("%Y%m%d%H%M%S"),
userid=self.context["request"].user.id,
ranstr=random_ins.randint(10, 99))
return order_sn
由时间串加用户id加随机字符串。10-99生成我们的订单编号
注意在 Serializer 中和 view 中取当前用户的不同方法。
def validate(self, attrs):
attrs["order_sn"] = self.generate_order_sn()
return attrs
在 validate 中完成之后,在 view 中就可以直接调用 save() 方法了
def perform_create(self, serializer):
order = serializer.save()
# 获取用户购物车的商品
shop_carts = ShoppingCart.objects.filter(user=self.request.user)
for shop_cart in shop_carts:
order_goods = OrderGoods()
order_goods.goods = shop_cart.goods
order_goods.goods_num = shop_cart.nums
order_goods.order = order
order_goods.save()
shop_cart.delete()
return order
现在我们就拿到 order 了
获取到购物车里面的商品,然后进行 for 循环的遍历生成订单的商品项目并保存
清空购物车然后 return order
配置订单的URL
# 配置订单相关的路由
router.register(r'orders', OrderViewSet, base_name="orders")
订单的状态不应该是用户可以提交的值。所以为订单状态添加 read_only
pay_status = serializers.CharField(read_only=True)
trade_no = serializers.CharField(read_only=True)
order_sn = serializers.CharField(read_only=True)
pay_time = serializers.DateTimeField(read_only=True)
同理可得的有交易号,订单号,支付时间等。
删除订单的时候,我们需要生成订单时返回的id。删除订单时我们将订单中的商品项一起删除掉。
首先是结算页面。订单的接口中没有商品的具体信息。
trade/views.py进行动态的Serializer的选择
def get_serializer_class(self):
if self.action == "retrieve":
return OrderDetailSerializer
return OrderSerializer
trade/serializers.py新建OrderDetailSerializer类
class OrderDetailSerializer(serializers.ModelSerializer):
goods = OrderGoodsSerializer(many=True)
class Meta:
model = OrderInfo
fields = "__all__"
其中的goods字段嵌套一个OrderGoodsSerializer
trade/serializers.py添加OrderGoodsSerialzier:
class OrderGoodsSerializer(serializers.ModelSerializer):
goods = GoodsSerializer(many=False)
class Meta:
model = OrderGoods
fields = "__all__"
orderGoodsSerializer用于goods详情的序列化。
订单与订单内的商品项是通过order进行关联的。
第一个goods实际上是外键关系,内层嵌套的goods才是我们的商品详情
订单状态是未支付的时候会显示支付宝支付的按钮。