【Django REST framework电商项目笔记】第10章 购物车, 订单和支付宝支付功能(中)

订单管理接口实现

首先理解一下购物车和订单之间的关系。
我们现在是做了一种最简单的实现就是把购物车中所有商品进行一起的结算
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。删除订单时我们将订单中的商品项一起删除掉。

vue订单接口调试

首先是结算页面。订单的接口中没有商品的具体信息。

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才是我们的商品详情
订单状态是未支付的时候会显示支付宝支付的按钮。

你可能感兴趣的:(Django)