美多商城项目之购物车模块
美多商城的购物车逻辑,主要分为登录用户的购物车和未登录用户的购物车。
登录用户的购物车:我们通过Redis数据库进行存储,使用HASH表存储购物车商品信息,使用Set存储购物车中被勾选的商品。
未登录用户的购物车:我们通过COOKIE进行存储。
1. 购物车的存储方案如下:
1.1 已登录的用户的购物车:
存储数据:商品(sku_id)、数量(count)、勾选状态(selected)
存储位置:redis
存储类型:
hash存储商品(sku_id)、数量(count)
set存储勾选状态(selected):那个商品被勾选,就将那个商品的sku_id存储到set中即可
存储逻辑:
1.判断要添加的商品在购物车中是否存在
2.如果不存在,直接保存记录
3.如果存在,直接累加数量
存储效果:
carts_user_id: {sku_id1: count1, sku_id2: count2}
selected_user_id: [sku_id1]
1.2 未登录用户的购物车:
存储数据:商品(sku_id)、数量(count)、勾选状态(selected)
存储位置:用户浏览器的cookie
存储类型:
购物车密文字符串
存储逻辑:
1.判断要添加的商品在购物车中是否存在
2.如果不存在,直接保存记录
3.如果存在,直接累加数量
存储效果:
JASJ8723447ASDNAKCSCSKC187Y28KAJCN7645397JFJFHF64759JHSFSKFJHB==
1.3 如何操作未登录用户的购物车呢?
我们是用COOKIE来保存未登录用户的购物车信息,那么我们就需要构造一个字符串数据。
这个字符串数据的结构应该是一个字典。
将购物车密文字符串转购物车字典:
# 先读取cookie中的购物车密文字符串
cart_str = request.COOKIES.get('carts')
# 然后将购物车密文字符串转成bytes类型字符串
cart_str_bytes = cart_str.encode()
# 再使用base64将bytes类型字符串解码为bytes类型字典
cart_dict_bytes = base64.b64decode(cart_str_bytes)
# 最后使用pickle将bytes类型字典反序列化成python字典
cart_dict = pickle.loads(cart_dict_bytes)
将购物车字典转购物车密文字符串
# 先使用pickle将购物车字典序列化成bytes类型字典
cart_dict_bytes = pickle.dumps(cart_dict)
# 然后使用base64将bytes类型字典编码为bytes类型字符串
cart_str_bytes = base64.b64encode(cart_dict_bytes)
# 再将bytes类型字符串转成购物车字符串
cookie_cart_str = cart_str_bytes.decode()
# 最后将购物车字符串写入到cookie中
response.set_cookie('carts', cookie_cart_str)
2. 购物车管理:
2.1 新增购物车
2.1.1 实现逻辑
1.判断要添加的商品在购物车中是否存在
2.如果不存在,直接保存记录
3.如果存在,直接累加数量
2.1.2 用户已登录
pl.hincrby('carts_%s' % user.id, sku_id, count)
if selected:
pl.sadd('selected_%s' % user.id, sku_id)
2.1.3 用户未登录
if sku_id in cart_dict:
origin_count = cart_dict[sku_id]['count']
count += origin_count
cart_dict[sku_id] = {
"count": count,
"selected": selected
}
2.2 查询购物车
2.2.1 用户已登录
核心思想:查询该用户在redis中存储的所有的购物车信息
实现方式:
redis_cart = redis_conn.hgetall('carts_%s' % user.id)
redis_selected = redis_conn.smembers('selected_%s' % user.id)
2.2.2 用户未登录
核心思想:查询该用户在cookie中存储的所有的购物车信息
实现方式:就是从cookie中读取购物车字典即可
2.3 修改购物车
2.3.1 用户已登录
核心思想:直接使用新的购物车数据覆盖旧的购物车数据
实现方式:
pl.hset('carts_%s' % user.id, sku_id, count)
if selected:
pl.sadd('selected_%s' % user.id, sku_id)
else:
pl.srem('selected_%s' % user.id, sku_id)
2.3.2 用户未登录
核心思想:直接使用新的购物车数据覆盖旧的购物车数据
实现方式:
cart_dict[sku_id] = {
"count": count,
"selected": selected }
2.4 删除购物车
2.4.1 用户已登录
核心思想:直接删除指定商品即可
实现方式:
pl.hdel('carts_%s' % user.id, sku_id)
pl.srem('selected_%s' % user.id, sku_id)
2.4.2 用户未登录
核心思想:直接删除指定商品即可
实现方式:
if sku_id in cart_dict:
del cart_dict[sku_id]
2.5全选购物车
2.5.1 用户已登录
核心思想:如果用户选择全选,那么将购物车中所有商品的sku_id添加到set中,反之,从set中移除sku_id
实现方式:
redis_cart = redis_conn.hgetall('carts_%s' % user.id)
cart_sku_ids = redis_cart.keys()
if selected:
redis_conn.sadd('selected_%s' % user.id, *cart_sku_ids)
else:
redis_conn.srem('selected_%s' % user.id, *cart_sku_ids)
2.5.2 用户未登录
核心思想:如果用户选择全选,那么将购物车字典中所有的selected设置为True,反之,设置为False
实现方式:
for sku_id in cart_dict:
cart_dict[sku_id]['selected'] = selected
3. 购物车合并逻辑:
购物车合并逻辑有三种,一种是以COOKIE为主,一种是以Redis为主,一种是将COOKIE和Redis中的数据做累加操作。
3.1 合并时机:账号登录和QQ登录时都要合并购物车
3.2 合并方向:cookie购物车数据合并到Redis购物车数据中
3.3 合并数据:购物车商品数据(sku_id、数量)和勾选状态
3.4 合并逻辑:
3.4.1 以cookie中购物车数据为主
3.4.2 判断cookie中的购物车数据在Redis数据库中是否存在
3.4.3 如果已存在,将cookie购物车数据覆盖Redis购物车数据
3.4.4 如果不存在,将cookie购物车数据新增到Redis
3.4.5 最终商品的勾选状态以cookie购物车勾选状态为主
3.4.6 Redis数据库中独有的购物车数据自己保留