【Vue+DRF 生鲜电商】购物车和订单管理(七)

1. 购物车

接口:http://127.0.0.1:8000/shopcarts/

需求:

  • 添加商品到购物车
  • 购物车中所有商品信息(详情)
  • 删除购物车记录

1.1 添加商品到购物车

1、trade/seriliazers.py

class ShopCartSerializer(serializers.Serializer):
    """购物车"""
    # 获取当前登录用户
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    nums = serializers.IntegerField(required=True, label='数量', min_value=1,
                                    error_messages={
                                        'min_value': '商品数量不能小于一',
                                        'required': '请选择购买数量'
                                    })
    # 外键,获取 goods 中所有值,必须指定 queryset,继承 ModelSerializer 无需指定
    goods = serializers.PrimaryKeyRelatedField(required=True, queryset=Goods.objects.all())
    add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M")

    def create(self, validated_data):
        """
        serializers.Serializer 没有 save() 需要重写 create
        :param validated_data:已处理过的数据(前端提交的数据)
        :return:
        """
        # 获取当前用户
        user = self.context['request'].user
        nums = validated_data['nums']
        goods = validated_data['goods']

        # 查询数据库,若有记录(表示添加到购物车,该商品),数量 + nums,否则就添加到购物车
        existed = ShoppingCart.objects.filter(user=user, goods=goods)

        # 数量增加
        if existed:
            existed = existed[0]
            existed.nums += nums
            existed.save()
        else:
            # 添加到购物车
            existed = ShoppingCart.objects.create(**validated_data)

        return existed

    def update(self, instance, validated_data):
        """更新购物车,修改数量"""
        instance.nums = validated_data['nums']
        instance.save()
        return instance

这里之所以采用继承 Serializer 而不是 ModelSerializer,是因为 ModelSerializer 的 creat() 方法会之前创建一条新的记录,当用户将同一商品多次添加到购物车时应该只需数量变化,而不是重写创建一条新的购物车记录,所以需要重写 create() 方法。

2、trade/views.py

class ShoppingCartViewSet(viewsets.ModelViewSet):
    """
    购物车功能:
    list:获取购物车详情
    create:加入购物车
    delete:删除购物车记录
    """
    serializer_class = ShopCartSerializer
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

    # 商品 ID,用于购物车更新(update() 商品数量)
    lookup_field = "goods_id"

    def get_queryset(self):
        """获取当前用户购物车列表"""
        return ShoppingCart.objects.filter(user=self.request.user)

3、配置路由 MxShop/urls.py

router.register(r'shopcarts', ShoppingCartViewSet, basename='shopcarts')  # 购物车

1.2 获取购物车商品详情

接口:

# 获取所有商品信息:get
http://127.0.0.1:8000/shopcarts/

# 单独获取某个商品详情:get
http://127.0.0.1:8000/shopcarts/1/

1、trade/serializers.py

class ShopCartDetailSerializer(serializers.ModelSerializer):
    """购物车中商品详情"""
    # 一个购物车对应一个商品.
    goods = GoodsSerializer(many=False, required=True)

    class Meta:
        model = ShoppingCart
        fields = ('goods', 'nums')

2、trade/views.py

class ShoppingCartViewSet(viewsets.ModelViewSet):
    ....
    def get_serializer_class(self):
        """动态选择 serializer"""
        if self.action == 'list':
            return ShopCartDetailSerializer
        else:
            return ShopCartSerializer

动态选择 serializer,当添加或删除购物车商品时:ShopCartSerializer,获取购物车商品详情(列表)时:ShopCartDetailSerializer

2. 订单管理

接口地址:http://127.0.0.1:8000/orders/

需求分析:

  • 用户添加商品到购物车,点击结算
  • 填上地址留言(必须),结算(提交)订单
  • 会员中心可查看所以的订单列表,点击单个订单可查看订单详细信息

支持:创建订单、获取个人订单(列表、详情)、删除订单

1、trade/serializers.py

class OrderGoodsSerializer(serializers.ModelSerializer):
    """订单中的商品"""
    goods = GoodsSerializer(many=False)

    class Meta:
        model = OrderGoods
        fields = '__all__'


class OrderDetailSerializer(serializers.ModelSerializer):
    """
    订单中商品详细信息
    """
    # goods字段需要嵌套一个OrderGoodsSerializer
    goods = OrderGoodsSerializer(many=True)
    add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M")

    class Meta:
        model = OrderInfo
        fields = '__all__'


class OrderSerializer(serializers.ModelSerializer):
    """订单"""
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )

    # 生成订单时,不需 post以下数据
    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)
    nonce_str = serializers.CharField(read_only=True)
    pay_type = serializers.CharField(read_only=True)

    add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M")

    def generate_order_sn(self):
        """
        生成订单号:当前时间+userid+随机数
        :return:
        """
        from random import Random
        random_str = 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_str.randint(10, 99))
        return order_sn

    def validate(self, attrs):
        """validate 中添加 order_sn,然后再 view 中就可以 save"""
        attrs['order_sn'] = self.generate_order_sn()
        return attrs

    class Meta:
        model = OrderInfo
        fields = '__all__'

三个 serializer

  • OrderGoodsSerializer:订单中商品(OrderGoods
  • OrderDetailSerializer:订单中商品详细信息(OrderInfo
  • OrderSerializer:订单(OrderInfo

前端 vue 页面中需要提交的信息只有 订单留言、订单金额、收货地址、签收人、联系电话,其他诸如 订单号、支付状态、交易号等不需要在前端提交

流程:表单字段验证通过后,validate() 中调用 generate_order_sn() 生成订单号,并将其保存到 attrs 字典中,之后 view 视图 save() 保存,订单创建成功。

2、trade/views.py

class OrderViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin,
                   mixins.RetrieveModelMixin):
    """
    订单相关
    list:获取个人订单
    create:创建订单
    delete:删除订单
    """
    serializer_class = OrderSerializer
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

    def get_serializer_class(self):
        # 订单详情
        if self.action == 'retrieve':
            return OrderDetailSerializer
        else:
            return OrderSerializer

    def perform_create(self, serializer):
        """
        提交订单之前步骤
            1、将购物车中商品保存到 OrderGoods
            2、清空购物车
        :param serializer:
        :return:
        """
        order = serializer.save()
        # 获取购物车中所有商品
        shop_carts = ShoppingCart.objects.filter(user=self.request.user)
        for shop in shop_carts:
            order_goods = OrderGoods()
            order_goods.goods = shop.goods
            order_goods.goods_num = shop.nums
            order_goods.order = order
            order_goods.save()

            # 清空购物车
            shop.delete()

        return order

    def get_queryset(self):
        return OrderInfo.objects.filter(user=self.request.user)

保存之前将购物车中商品保存到 OrderGoods 中,另外就是清空购物车。

3、配置路由 MxShop/urls.py

router.register(r'orders', OrderViewSet, basename='orders')  # 订单

原文地址:https://www.cnblogs.com/midworld/p/13629732.html