修改购物车数据

1. 后端接口设计

请求方式 : PUT /cart/

请求参数: JSON 或 表单

参数 类型 是否必须 说明
sku_id int 商品sku id
count int 数量
selected bool 是否勾选,默认勾选

返回数据: JSON

参数 类型 是否必须 说明
sku_id int 商品sku id
count int 数量
selected bool 是否勾选,默认勾选

2. 后端实现

在carts/views.py中修改视图,添加put方法

 class CartView(APIView):
    ...

    def put(self, request):
        """
        购物车记录更新:
        """
        # 1. 获取参数并进行校验(sku_id, count, selected)
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        sku_id = serializer.validated_data['sku_id']
        count = serializer.validated_data['count']
        selected = serializer.validated_data['selected']

        # 2. 获取user
        try:
            # 获取user时会执行使用认证机制进行认证,因为客户端传递了jwt 数据
            # 如果认证失败,这句代码会报错
            user = request.user
        except Exception:
            user = None

        # 3. 更新购物车记录
        if user is not None and user.is_authenticated:
            # 3.1 如果用户已登录,更新redis中购物车记录
            redis_conn = get_redis_connection('cart')
            pl = redis_conn.pipeline()

            # 设置用户购物车中商品的id和对应数量count hash
            cart_key = 'cart_%s' % user.id
            # hset(key, field, value): 设置hash中某个属性值
            pl.hset(cart_key, sku_id, count)

            # 设置用户购物车中商品的勾选状态 set
            cart_selected_key = 'cart_selected_%s' % user.id
            if selected:
                # 勾选
                # sadd(key, *values): 向set中添加元素
                pl.sadd(cart_selected_key, sku_id)
            else:
                # 不勾选
                # srem(name, *values): 从set中移除元素,如果元素不存在,直接忽略
                pl.srem(cart_selected_key, sku_id)

            pl.execute()

            # 返回应答
            return Response(serializer.data)
        else:
            response = Response(serializer.data)
            # 3.2 如果用户未登录,更新cookie中购物车记录
            cookie_cart = request.COOKIES.get('cart') # None

            if cookie_cart is None:
                return response

            # 解析购物车中数据
            cart_dict = pickle.loads(base64.b64decode(cookie_cart)) # {}

            if not cart_dict:
                return response

            # 设置用户购物车商品数量count和勾选状态
            cart_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            # 4. 返回应答
            # 处理
            cookie_data = base64.b64encode(pickle.dumps(cart_dict)).decode()  # str

            # 设置购物车cookie信息
            response.set_cookie('cart', cookie_data, expires=constants.CART_COOKIE_EXPIRES)
            return response

3. 前端实现

在cart.js中添加

        on_input: function(index){
            var val = parseInt(this.cart[index].count);
            if (isNaN(val) || val <= 0) {
                this.cart[index].count = this.origin_input;
            } else {
                // 更新购物车数据
                axios.put(this.host+'/cart/', {
                        sku_id: this.cart[index].id,
                        count: val,
                        selected: this.cart[index].selected
                    }, {
                        headers:{
                            'Authorization': 'JWT ' + this.token
                        },
                        responseType: 'json',
                        withCredentials: true
                    })
                    .then(response => {
                        this.cart[index].count = response.data.count;
                    })
                    .catch(error => {
                        if ('non_field_errors' in error.response.data) {
                            alert(error.response.data.non_field_errors[0]);
                        } else {
                            alert('修改购物车失败');
                        }
                        console.log(error.response.data);
                        this.cart[index].count = this.origin_input;
                    })
            }
        },
        // 更新购物车数据
        update_count: function(index, count){
            axios.put(this.host+'/cart/', {
                    sku_id: this.cart[index].id,
                    count,
                    selected: this.cart[index].selected
                }, {
                    headers:{
                        'Authorization': 'JWT ' + this.token
                    },
                    responseType: 'json',
                    withCredentials: true
                })
                .then(response => {
                    this.cart[index].count = response.data.count;
                })
                .catch(error => {
                    if ('non_field_errors' in error.response.data) {
                        alert(error.response.data.non_field_errors[0]);
                    } else {
                        alert('修改购物车失败');
                    }
                    console.log(error.response.data);
                })
        },
        // 更新购物车数据
        update_selected: function(index) {
            axios.put(this.host+'/cart/', {
                    sku_id: this.cart[index].id,
                    count: this.cart[index].count,
                    selected: this.cart[index].selected
                }, {
                    headers: {
                        'Authorization': 'JWT ' + this.token
                    },
                    responseType: 'json',
                    withCredentials: true
                })
                .then(response => {
                    this.cart[index].selected = response.data.selected;
                })
                .catch(error => {
                    if ('non_field_errors' in error.response.data) {
                        alert(error.response.data.non_field_errors[0]);
                    } else {
                        alert('修改购物车失败');
                    }
                    console.log(error.response.data);
                })
        }