需求:用户登录时,将cookie购物车数据合并到Redis购物车数据中。
QQ登录和账号登录时都要进行购物车合并操作
二、购物车存储方案
## 1、存储数据分析
- 相对于用户登录和未登录状态下的区别是,是否有用户id 进行绑定,购物车内信息相同
- 当商品详情页面添加到购物车时,此时商品信息只有一条
* 商品相关信息、数量、
- 当在购物车列表页面时,此时商品信息可能多条,且存在某一条信息是否选择的情况
* 购物车每一条记录包含 : 商品相关信息、数量、是否勾选
- 归纳总结后可得到:购物车每条记录应包含基本信息为:
* 用户id: ser_id,未登录没用,可以用本机机器码代替,或保存到本地cookie中
* 商品信息唯一标识: sku_id
* 数量:count
* 选择标志:selected,商品详情页面添加时,可能没有设此参数,因只有一条,可以设置缺省选择
- 购物车存储方案可以有很多种,本项目约定如下:
* 购物车分用户登录和未登录两种情况,区别对待,都需存储
## 2、登录用户购物车存储方案
### 2.1 存储数据说明:
- 存储数据:user_id,sku_id,count,selected
### 2.2 存储位置说明
- 购物车数据量小,结构简单,更新频繁,所以我们选择内存型数据库Redis进行存储。
- 存储位置:Redis数据库 4号库
```python
# /lgshop/dev.py
"carts": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/4",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
合并购物车
由于登录与未登录放入购物车里的数据存放的位置不一样
合并方案:
合并购物车最终要将cookie里的数据放到redis里面
保存规则:
相同的商品用cookie覆盖redis
redis当中有的cookie里面没有 保留redis中的
勾选状态以cookies为准的
1.获取cookies中的购物车数据
2.判断cookies中的购物车数据是否存在
3.如果存在需要合并
4.如果不存在,不需要合并
5.准备新的数据容器 保存新的数据 sku_id count selected unselected
6.遍历出cookies中的购物车数据
7.根据新的数据结构 合并到redis中 将cookies中的数据调整成redis中一样
如cookie里面: sku_1 2 True
sku_2 2 False
redis里面: sku_1 2
sku_3 2
合并购物车逻辑实现
新建文件:carts.utils.py
# @Time:2021/4/3 14:12
# @Author:Ellen
# @File:utils.py
import base64, pickle
from django_redis import get_redis_connection
def merge_carts_cookies_redis(request, user, response):
'''
1.获取cookies中的购物车数据
2.判断cookies中的购物车数据是否存在
3.如果存在需要合并
4.如果不存在,不需要合并
5.准备新的数据容器 保存新的数据 sku_id count selected unselected
6.遍历出cookies中的购物车数据
7.根据新的数据结构 合并到redis中 将cookies中的数据调整成redis中一样
'''
# 获取cookies中的购物车数据
cart_str = request.COOKIES.get('carts')
if not cart_str and cart_str != 'gAN9cQAu':
return response
cookie_cart_str_bytes = cart_str.encode()
cookie_cart_dict_bytes = base64.b64decode(cookie_cart_str_bytes)
cookie_cart_dict = pickle.loads(cookie_cart_dict_bytes)
# {sku_id:count} selected=>[] unselect=>[]
new_cart_dict = {}
new_selected_add = []
new_selected_rem = []
# cart_dict = {'1': {'count': 10, 'selected': True}, '2': {'count': 20, 'selected': False}}
for sku_id, cookie_dict in cookie_cart_dict.items():
new_cart_dict[sku_id] = cookie_dict['count']
if cookie_dict['selected']:
new_selected_add.append(sku_id)
else:
new_selected_rem.append(sku_id)
# 重新写入到redis中
redis_conn = get_redis_connection('carts')
pl = redis_conn.pipeline()
pl .hmset('cart_%s' % user.id, new_cart_dict)
if new_selected_add:
pl.sadd('selected_%s' % user.id, *new_selected_add)
if new_selected_rem:
pl .srem('selected_%s' % user.id, *new_selected_rem)
pl.execute()
# 删除cookies
response.delete_cookie('carts')
return response
号和QQ登录合并购物车
在users.views.py和oauth.views.py文件中调用合并购物车的工具方法
users.views.py
# 登录成功后合并购物车
from carts.utils import merge_carts_cookies_redis
# 删除了cookies购物车的
response = merge_carts_cookies_redis(request, user, response)