完整电商项目--(七)购物车模块(1)

购物车存储方案

  • 分两种情况

用户登录

  • 描述一条完整的购物车记录需要
    • 用户、商品、数量、勾选状态
    • 存储数据:user_id、sku_id、count、selected
    • 存储位置:
      • 选择redis数据库
      • 数据存储类型
        • (1)选择hash类型,保存用户,商品,数量等信息。
          在这里插入图片描述
          存储的数据应为:carts_user_id: {sku_id1: count, sku_id3: count, sku_id5: count, …}

        • (2)勾选状态:采用set类型存储

        • 只将已勾选商品的sku_id存储到set中,比如,1号和3号商品是被勾选的

        • 形式selected_user_id: [sku_id1, sku_id3, …]

1111111111111111111111111111111111

  • 存储逻辑说明
    • 当要添加到购物车的商品已存在时,对商品数量进行累加计算
    • 当要添加到购物车的商品不存在时,向hash中新增field和value即可

用户未登录

存储数据

  • 和上面是一样的user_id、sku_id、count、selected

存储位置

  • 由于用户未登录,服务端无法拿到用户的ID
  • 我们可以将未登录用户的购物车数据缓存到用户浏览器的cookie中,每个用户自己浏览器的cookie中存储属于自己的购物车数据

存储类型

  • (1)浏览器的cookie中存储的数据类型是字符串
  • (2)JSON字符串可以描述复杂结构的字符串数据,可以保证一条购物车记录不用分开存储
  • 数据结构展示
{
    
    
    "sku_id1":{
    
    
        "count":"1",
        "selected":"True"
    },
    "sku_id3":{
    
    
        "count":"3",
        "selected":"True"
    },
    "sku_id5":{
    
    
        "count":"3",
        "selected":"False"
    }
}

存储逻辑说明

  • 当要添加到购物车的商品已存在时,对商品数量进行累加计算。
  • 当要添加到购物车的商品不存在时,向JSON中新增field和value即可

数据安全处理:

  • (1)浏览器cookie中存储的是字符串明文数据
    • 我们需要对数据进行加密
  • (2) 解决方案:pickle模块 和 base64模块

pickle模块介绍

  • pickle模块是Python的标准模块,提供了对Python数据的序列化操作,可以将数据转换为bytes类型,且序列化速度快
  • 使用方法:
    • pickle.dumps()将Python数据序列化为bytes类型数据
    • pickle.loads()将bytes类型数据反序列化为python数据。

base64模块介绍

  • 注意!!! : pickle模块序列化转换后的数据是bytes类型,浏览器cookie无法存储
  • 介绍:
    • base64模块是Python的标准模块,可以对bytes类型数据进行编码,并得到bytes类型的密文数据
    • 使用:
      • base64.b64encode()将bytes类型数据进行base64编码,返回编码后的bytes类型数据
      • base64.b64deocde()将base64编码后的bytes类型数据进行解码,返回解码后的bytes类型数据。

下面是具体的代码实现

增加购物车

redis中

在这里插入图片描述

redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # 新增购物车数据
            pl.hincrby('carts_%s' % user.id, sku_id, count)
            # 新增选中的状态
            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)
            # 执行管道
            pl.execute()

cookie中

# 用户未登录,操作cookie购物车
            cart_str = request.COOKIES.get('carts')
            # 如果用户操作过cookie购物车
            if cart_str:
                # 将cart_str转成bytes,再将bytes转成base64的bytes,最后将bytes转字典
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:  # 用户从没有操作过cookie购物车
                cart_dict = {
    
    }

            # 判断要加入购物车的商品是否已经在购物车中,如有相同商品,累加求和,反之,直接赋值
            if sku_id in cart_dict:
                # 累加求和
                origin_count = cart_dict[sku_id]['count']
                count += origin_count
            cart_dict[sku_id] = {
    
    
                'count': count,
                'selected': selected
            }
            # 将字典转成bytes,再将bytes转成base64的bytes,最后将bytes转字符串
            cookie_cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()

            # 创建响应对象
            response = http.JsonResponse({
    
    'code': RETCODE.OK, 'errmsg': '添加购物车成功'})
            # 响应结果并将购物车数据写入到cookie
            response.set_cookie('carts', cookie_cart_str, max_age=constants.CARTS_COOKIE_EXPIRES)

删除购物车

redis中

 redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # 删除键,就等价于删除了整条记录
            pl.hdel('carts_%s' % user.id, sku_id)
            pl.srem('selected_%s' % user.id, sku_id)
            pl.execute()

删除cookie购物车

cart_str = request.COOKIES.get('carts')
            if cart_str:
                # 将cart_str转成bytes,再将bytes转成base64的bytes,最后将bytes转字典
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart_dict = {
    
    }

            # 创建响应对象
            response = http.JsonResponse({
    
    'code': RETCODE.OK, 'errmsg': '删除购物车成功'})
            if sku_id in cart_dict:
                del cart_dict[sku_id]
                # 将字典转成bytes,再将bytes转成base64的bytes,最后将bytes转字符串
                cookie_cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
                # 响应结果并将购物车数据写入到cookie
                response.set_cookie('carts', cookie_cart_str, max_age=constants.CARTS_COOKIE_EXPIRES)
            return response

其余的修改,展示购物车都是类似的,这里就不说了

全选购物车

redis中:

# 用户已登录,操作redis购物车
            redis_conn = get_redis_connection('carts')
            cart = redis_conn.hgetall('carts_%s' % user.id)
            sku_id_list = cart.keys()
            if selected:
                # 全选
                redis_conn.sadd('selected_%s' % user.id, *sku_id_list)
            else:
                # 取消全选
                redis_conn.srem('selected_%s' % user.id, *sku_id_list)
            return http.JsonResponse({
    
    'code': RETCODE.OK, 'errmsg': '全选购物车成功'})

cookie中

# 用户已登录,操作cookie购物车
            cart = request.COOKIES.get('carts')
            response = http.JsonResponse({
    
    'code': RETCODE.OK, 'errmsg': '全选购物车成功'})
            if cart is not None:
                cart = pickle.loads(base64.b64decode(cart.encode()))
                for sku_id in cart:
                    cart[sku_id]['selected'] = selected
                cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()
                response.set_cookie('carts', cookie_cart, max_age=constants.CARTS_COOKIE_EXPIRES)

合并购物车

# 获取cookie中的购物车数据
    cookie_cart_str = request.COOKIES.get('carts')
    # cookie中没有数据就响应结果
    if not cookie_cart_str:
        return response
    cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart_str.encode()))

    new_cart_dict = {
    
    }
    new_cart_selected_add = []
    new_cart_selected_remove = []
    # 同步cookie中购物车数据
    for sku_id, cookie_dict in cookie_cart_dict.items():
        new_cart_dict[sku_id] = cookie_dict['count']

        if cookie_dict['selected']:
            new_cart_selected_add.append(sku_id)
        else:
            new_cart_selected_remove.append(sku_id)

    # 将new_cart_dict写入到Redis数据库
    redis_conn = get_redis_connection('carts')
    pl = redis_conn.pipeline()
    pl.hmset('carts_%s' % user.id, new_cart_dict)
    # 将勾选状态同步到Redis数据库
    if new_cart_selected_add:
        pl.sadd('selected_%s' % user.id, *new_cart_selected_add)
    if new_cart_selected_remove:
        pl.srem('selected_%s' % user.id, *new_cart_selected_remove)
    pl.execute()

    # 清除cookie
    response.delete_cookie('carts')

就到这里吧,全是增删改查,操作cookie和redis,其实很繁琐,但是不是很难,大家仔细看懂逻辑实现就可以。

猜你喜欢

转载自blog.csdn.net/pythonstrat/article/details/108183169