2.5 全选购物车
提示:在购物车页面修改购物车使用局部刷新的效果。
2.5.1. 全选购物车接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /carts/selection/ |
# 全选购物车
url(r'^carts/selection/$', views.CartsSelectAllView.as_view()),
2.请求参数:JSON
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
selected | bool | 是 | 是否全选 |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
4.后端接口定义
class CartsSelectAllView(View):
"""全选购物车"""
def put(self, request):
# 接收和校验参数
# 判断用户是否登录
user = request.user
if user.is_authenticated:
# 用户已登录,操作redis购物车
pass
else:
# 用户未登录,操作cookie购物车
pass
2.5.2. 全选购物车后端逻辑实现
1.接收和校验参数
class CartsSelectAllView(View):
"""全选购物车"""
def put(self, request):
# 接收参数
json_dict = json.loads(request.body.decode())
selected = json_dict.get('selected', True)
# 校验参数
if selected:
if not isinstance(selected, bool):
return http.HttpResponseForbidden('参数selected有误')
# 判断用户是否登录
user = request.user
if user is not None and user.is_authenticated:
# 用户已登录,操作redis购物车
pass
else:
# 用户已登录,操作cookie购物车
pass
2.全选Redis购物车
class CartsSelectAllView(View):
"""全选购物车"""
def put(self, request):
# 接收和校验参数
......
# 判断用户是否登录
user = request.user
if user is not None and user.is_authenticated:
# 用户已登录,操作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': '全选购物车成功'})
else:
# 用户已登录,操作cookie购物车
pass
3.全选cookie购物车
class CartsSelectAllView(View):
"""全选购物车"""
def put(self, request):
# 接收和校验参数
......
# 判断用户是否登录
user = request.user
if user is not None and user.is_authenticated:
# 用户已登录,操作redis购物车
......
else:
# 用户已登录,操作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)
return response
2.6 合并购物车
需求:用户登录时,将cookie
购物车数据合并
到Redis
购物车数据中。
提示:
QQ登录
和账号登录
时都要进行购物车合并操作。
2.6.1. 合并购物车逻辑分析
1.合并方向:cookie购物车数据合并到Redis购物车数据中。
2.合并数据:购物车商品数据和勾选状态。
3.合并方案:
3.1 Redis数据库中的购物车数据保留。
3.2 如果cookie中的购物车数据在Redis数据库中已存在,将cookie购物车数据覆盖Redis购物车数据。
3.3 如果cookie中的购物车数据在Redis数据库中不存在,将cookie购物车数据新增到Redis。
3.4 最终购物车的勾选状态以cookie购物车勾选状态为准。
2.6.2. 合并购物车逻辑实现
新建文件:carts.utils.py
from django_redis import get_redis_connection
import pickle
import base64
def merge_cart_cookie_to_redis(request, user, response):
"""
登录后合并cookie购物车数据到Redis
:param request: 本次请求对象,获取cookie中的数据
:param response: 本次响应对象,清除cookie中的数据
:param user: 登录用户信息,获取user_id
:return: response
"""
# 获取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')
return response
3. 账号和QQ登录合并购物车
在users.views.py
和oauth.views.py
文件中调用合并购物车的工具方法
# 合并购物车
response = merge_cart_cookie_to_redis(request=request, user=user, response=response)