添加到购物车

Posted hzlnice

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了添加到购物车相关的知识,希望对你有一定的参考价值。

1. 后端接口设计

请求方式 : POST /cart/

请求参数: JSON 或 表单

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

返回数据: JSON

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

访问此接口,无论用户是否登录,前端请求都需携带请求头Authorization,由后端判断是否登录

2. 后端实现

因为前端可能携带cookie,为了保证跨域请求中,允许后端使用cookie,确保在配置文件有如下设置

CORS_ALLOW_CREDENTIALS = True

创建应用carts。

在carts/serialziers.py中创建序列化器

class CartSerializer(serializers.Serializer):
    """
    购物车数据序列化器
    """
    sku_id = serializers.IntegerField(label=‘sku id ‘, min_value=1)
    count = serializers.IntegerField(label=‘数量‘, min_value=1)
    selected = serializers.BooleanField(label=‘是否勾选‘, default=True)

    def validate(self, data):
        try:
            sku = SKU.objects.get(id=data[‘sku_id‘])
        except SKU.DoesNotExist:
            raise serializers.ValidationError(‘商品不存在‘)

        if data[‘count‘] > sku.stock:
            raise serializers.ValidationError(‘商品库存不足‘)

        return data

编写视图:

注意:因为前端请求时携带了Authorization请求头(主要是JWT),而如果用户未登录,此请求头的JWT无意义(没有值),为了防止REST framework框架在验证此无意义的JWT时抛出401异常,在视图中需要做两个处理

  • 重写perform_authentication()方法,此方法是REST framework检查用户身份的方法
  • 在获取request.user属性时捕获异常,REST framework在返回user时,会检查Authorization请求头,无效的Authorization请求头会导致抛出异常

在carts/views.py中创建视图

class CartView(APIView):
    """
    购物车
    """
    def perform_authentication(self, request):
        """
        重写父类的用户验证方法,不在进入视图前就检查JWT
        """
        pass

    def post(self, request):
        """
        添加购物车
        """
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.validated_data.get(‘sku_id‘)
        count = serializer.validated_data.get(‘count‘)
        selected = serializer.validated_data.get(‘selected‘)

        # 尝试对请求的用户进行验证
        try:
            user = request.user
        except Exception:
            # 验证失败,用户未登录
            user = None

        if user is not None and user.is_authenticated:
            # 用户已登录,在redis中保存
            redis_conn = get_redis_connection(‘cart‘)
            pl = redis_conn.pipeline()
            # 记录购物车商品数量
            pl.hincrby(‘cart_%s‘ % user.id, sku_id, count)
            # 记录购物车的勾选项
            # 勾选
            if selected:
                pl.sadd(‘cart_selected_%s‘ % user.id, sku_id)
            pl.execute()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            # 用户未登录,在cookie中保存
            # {
            #     1001: { "count": 10, "selected": true},
            #     ...
            # }
            # 使用pickle序列化购物车数据,pickle操作的是bytes类型
            cart = request.COOKIES.get(‘cart‘)
            if cart is not None:
                cart = pickle.loads(base64.b64decode(cart.encode()))
            else:
                cart = {}

            sku = cart.get(sku_id)
            if sku:
                count += int(sku.get(‘count‘))

            cart[sku_id] = {
                ‘count‘: count,
                ‘selected‘: selected
            }

            cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()

            response = Response(serializer.data, status=status.HTTP_201_CREATED)

            # 设置购物车的cookie
            # 需要设置有效期,否则是临时cookie
            response.set_cookie(‘cart‘, cookie_cart, max_age=constants.CART_COOKIE_EXPIRES)
            return response

在carts中新建constants.py 常量文件

# 购物车cookie的有效期
CART_COOKIE_EXPIRES = 365 * 24 * 60 * 60

以上是关于添加到购物车的主要内容,如果未能解决你的问题,请参考以下文章

如何从 recyclerview 片段传递到另一个 recyclerview 片段

Woocommerce:检测单击“添加到购物车”按钮的位置并运行不同的代码

如何将折扣代码添加到我的购物车并将其发送到贝宝结帐?

调整 WooCommerce 添加到购物车短代码的参数不起作用

如何正确地将多个片段添加到片段过渡?

在 Woocommerce 中将 ajax 添加到购物车事件后运行 javascript 代码