def merge_cart(request, response): # 这个方法使用在登录视图中,在登录时,请求报文request中不包含用户对象 # 当状态保持后,request.user才是一个有效的用户对象 # 从cookie中读取购物车数据 cart_str = request.COOKIES.get('cart') if not cart_str: # cookie中没有购物车数据 return response cart_dict = meiduo_json.loads(cart_str) # 向redis中保存购物车数据 user = request.user redis_cli = get_redis_connection('cart') redis_pipeline = redis_cli.pipeline() for sku_id, sku_dict in cart_dict.items(): # hash,存商品编号、数量 redis_pipeline.hset('cart%d' % user.id, sku_id, sku_dict.get('count')) # set,表示商品选中状态 if sku_dict.get('selected'): redis_pipeline.sadd('selected%d' % user.id, sku_id) redis_pipeline.execute() # 删除cookie中的购物车数据 response.delete_cookie('cart') # 返回响应对象,最终返回给浏览器 return response
def get(self, request): # 从购物车中读取数据 if request.user.is_authenticated: redis_cli = get_redis_connection('cart') sku_cart_bytes = redis_cli.hgetall('cart%d' % request.user.id) sku_cart_int = { int(sku_id): int(count) for sku_id, count in sku_cart_bytes.items() } else: cart_str = request.COOKIES.get('cart') if cart_str: cart_dict = meiduo_json.loads(cart_str) else: cart_dict = {} sku_cart_int = {} for sku_id, dict1 in cart_dict.items(): sku_cart_int[sku_id] = dict1.get('count') # 查询商品对象 skus = SKU.objects.filter(pk__in=sku_cart_int.keys()) # 遍历,构造前端需要的数据结构 sku_list = [] for sku in skus: sku_list.append({ 'id': sku.id, 'name': sku.name, 'count': sku_cart_int.get(sku.id), 'default_image_url': sku.default_image.url }) # 响应 return http.JsonResponse({ 'code': RETCODE.OK, 'errmsg': "OK", 'cart_skus': sku_list })
def merge_carts_cookie_to_redis(request, response): ''' 将cookie中的购物车数据转存到redis中 :param request: 请求对象 :param response: 响应对象 :return: 响应对象 以cookie中的数据覆盖redis中的数据 ''' user = request.user # 1.读取cookie中购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is None: return response cart_dict = meiduo_json.loads(cart_str) # 2.遍历,保存到redis中 redis_cli = get_redis_connection('carts') redis_pl = redis_cli.pipeline() for sku_id, cart in cart_dict.items(): # 向hash中添加数据 redis_pl.hset('cart%d' % user.id, sku_id, cart['count']) # 如果选中则向set中添加,如果不选中则删除set中的库存商品编号 if cart['selected']: redis_pl.sadd('selected%d' % user.id, sku_id) else: redis_pl.srem('selected%d' % user.id, sku_id) redis_pl.execute() # 3.删除cookie中购物车数据 response.delete_cookie('cart') return response
def get(self, request): # 处理: # 1.查询购物车数据 user = request.user cart_dict = {} if user.is_authenticated: # 已登录,从redis中获取购物车数据 redis_cli = get_redis_connection('carts') # hash===>sku_id,count cart = redis_cli.hgetall('cart%d' % user.id) # {1:2,2:3} # set=====>sku_id,即选中状态 selected = redis_cli.smembers('selected%d' % user.id) # [1,2,3] # 遍历,将bytes===>int for sku_id, count in cart.items(): cart_dict[int(sku_id)] = { 'count': int(count), 'selected': sku_id in selected } ''' { 16:{ 'count':1, 'selected':True }, ... } ''' else: # 未登录,从cookie中获取购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is not None: cart_dict = meiduo_json.loads(cart_str) # 2.查询库存商品对象 skus = SKU.objects.filter(pk__in=cart_dict.keys(), is_launched=True) # [15,16] # 3.遍历,转换成前端需要的格式 cart_skus = [] for sku in skus: count = cart_dict[sku.id]['count'] selected = cart_dict[sku.id]['selected'] cart_skus.append({ 'id': sku.id, 'name': sku.name, 'default_image_url': sku.default_image.url, 'price': str(sku.price), # js中没有decimal类型,需要转换成字符串再输出给js 'count': count, 'selected': str(selected), # js中bool类型为true或false,python中为True或False 'total_amount': str(sku.price * count) }) context = {'cart_skus': cart_skus} return render(request, 'cart.html', context)
def delete(self, request): ''' 删除购物车记录 :param sku_id:库存商品编号 ''' # 接收 param_dict = json.loads(request.body.decode()) sku_id = param_dict.get('sku_id') # 验证 if not all([sku_id]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # 2.2库存商品编号有效 try: sku = SKU.objects.get(pk=sku_id, is_launched=True) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '库存商品编号无效' }) # 处理:删除 user = request.user response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'}) if user.is_authenticated: # 已登录,则删除redis中的hash、set redis_cli = get_redis_connection('carts') redis_pl = redis_cli.pipeline() # 删除hash redis_pl.hdel('cart%d' % user.id, sku_id) # 删除set redis_pl.srem('selected%d' % user.id, sku_id) redis_pl.execute() else: # 未登录,则删除cookie中记录 # 1.读取cookie中购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is None: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '购物车无效' }) cart_dict = meiduo_json.loads(cart_str) # 2.删除指定的库存商品 if sku_id in cart_dict: del cart_dict[sku_id] # 3.写cookie response.set_cookie('cart', meiduo_json.dumps(cart_dict), max_age=constants.CART_EXPIRES) # 响应 return response
def get(self, request): # 读取购物车数据,做出简单提示 user = request.user cart_dict = {} # 1.查询购物车数据 if user.is_authenticated: redis_cli = get_redis_connection('carts') cart_dict = redis_cli.hgetall('cart%d' % user.id) cart_dict = { int(sku_id): int(count) for sku_id, count in cart_dict.items() } ''' { 库存商品编号1:数量1, 库存商品编号2:数量2, ... } ''' else: cart_str = request.COOKIES.get('cart') if cart_str is not None: ''' { 库存商品编号1:{ 'count':数量, 'selected':选中状态 }, .... } ''' cart_dict = meiduo_json.loads(cart_str) # 将字典结构统一 cart_dict = { sku_id: cart['count'] for sku_id, cart in cart_dict.items() } # 2.查询库存商品对象,转换成前端需要的格式 skus = SKU.objects.filter(pk__in=cart_dict.keys(), is_launched=True) sku_list = [] for sku in skus: sku_list.append({ 'id': sku.id, 'name': sku.name, 'default_image_url': sku.default_image.url, 'count': cart_dict[sku.id] }) return http.JsonResponse({ 'code': RETCODE.OK, 'errmsg': '', 'cart_skus': sku_list })
def put(self, request): ''' 设置购物车中的商品选中状态,要么全选中,要么全不选中 :param selected:选中状态,True,False ''' # 接收 param_dict = json.loads(request.body.decode()) selected = param_dict.get('selected', True) # 验证 if not isinstance(selected, bool): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '选中状态无效' }) # 处理 user = request.user response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': "ok"}) if user.is_authenticated: # 已登录,修改set中的值 redis_cli = get_redis_connection('carts') if selected: # 读取hash中所有库存商品编号 sku_ids = redis_cli.hkeys('cart%d' % user.id) # [1,2,3,4]===>1,2,3,4 # 如果选中,则将所有库存商品编号加入集合 redis_cli.sadd('selected%d' % user.id, *sku_ids) else: # 如果不选中,则将集合中所有的库存商品编号删除 redis_cli.delete('selected%d' % user.id) else: # 未登录,修改cookie中的值 # 1.读取cookie中购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is None: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '购物车无效' }) cart_dict = meiduo_json.loads(cart_str) # 2.遍历字典,修改selected属性 for sku_id, dict1 in cart_dict.items(): dict1['selected'] = selected # 3.写cookie response.set_cookie('cart', meiduo_json.dumps(cart_dict), max_age=constants.CART_EXPIRES) # 响应 return response
def put(self, request): # 全选、全不选 # 接收 dict1 = json.loads(request.body.decode()) selected = dict1.get('selected', True) # 验证 if not isinstance(selected, bool): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数类型错误' }) # selected=bool(selected) # 处理 response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'}) if request.user.is_authenticated: redis_cli = get_redis_connection('cart') # 从hash中获取所有商品编号 sku_ids = redis_cli.hkeys('cart%d' % request.user.id) if selected: # 如果选中则加入set,*表示解包[1,2,3]===>1,2,3 redis_cli.sadd('selected%d' % request.user.id, *sku_ids) else: # 如果不选中则删除set redis_cli.srem('selected%d' % request.user.id, *sku_ids) else: # 读取 cart_str = request.COOKIES.get('cart') # 解密 if cart_str: cart_dict = meiduo_json.loads(cart_str) else: cart_dict = {} # 修改{sku_id:{}} for sku_id in cart_dict: # {count:***,selected:***} # sku_dict=cart_dict[sku_id] # sku_dict['selected']=selected cart_dict[sku_id]['selected'] = selected # 加密 cart_str = meiduo_json.dumps(cart_dict) # 写 response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) # 响应 return response
def delete(self, request): json_dict = json.loads(request.body.decode()) sku_id = json_dict.get('sku_id') # 验证 if not all([sku_id]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # sku_id有效 try: sku = SKU.objects.get(pk=sku_id) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '商品编号无效' }) response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'}) if request.user.is_authenticated: redis_cli = get_redis_connection('cart') redis_cli.hdel('cart%d' % request.user.id, sku_id) redis_cli.srem('selected%d' % request.user.id, sku_id) else: # 读cookie cart_str = request.COOKIES.get('cart') if cart_str: cart_dict = meiduo_json.loads(cart_str) else: cart_dict = {} # 改写字典 if sku_id in cart_dict: del cart_dict[sku_id] # 写cookie cart_str = meiduo_json.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) return response
def get(self, request): # 读取购物车中的数据 if request.user.is_authenticated: # 已登录,从redis中读取 redis_cli = get_redis_connection('cart') # hash,包括商品编号、数量 cart_dict_bytes = redis_cli.hgetall('cart%d' % request.user.id) cart_dict_int = { int(sku_id): int(count) for sku_id, count in cart_dict_bytes.items() } # cart_dict_int2={} # for key,value in cart_dict_bytes.item(): # cart_dict_int2[int(key)]=int(value) # set,商品编号,表示选中的商品 selected_bytes = redis_cli.smembers('selected%d' % request.user.id) selected_int = [int(sku_id) for sku_id in selected_bytes] # print(cart_dict_bytes) else: # 未登录,从cookie中读取{sku_id:{selected:***,count:***}} cart_str = request.COOKIES.get('cart') if cart_str: cart_dict = meiduo_json.loads(cart_str) else: cart_dict = {} # 转换字典的结构 ''' cookie中数据的结构 { sku_id: { count:***, selected:*** } } 转换成如下结构,则与redis的后续代码一致 {sku_id:count,..} [sku_id,...] ''' cart_dict_int = {} selected_int = [] # 遍历字典value===>{count:***,selected:***} for sku_id, value in cart_dict.items(): # 将商品编号、数量存入字典中 cart_dict_int[sku_id] = value['count'] # 将商品选中状态存入列表中 if value['selected']: selected_int.append(sku_id) # 查询商品对象,构造页面中需要的数据[1,2,3] skus = SKU.objects.filter(pk__in=cart_dict_int.keys()) cart_skus = [] # 遍历商品对象 for sku in skus: # 构造前端需要的结构 cart_skus.append({ 'id': sku.id, 'selected': str(sku.id in selected_int), 'default_image_url': sku.default_image.url, 'name': sku.name, 'price': str(sku.price), 'count': cart_dict_int.get(sku.id), 'total_amount': str(cart_dict_int.get(sku.id) * sku.price) }) context = {'cart_skus': cart_skus} return render(request, 'cart.html', context)
def put(self, request): # 修改 # 接收、验证 json_dict = json.loads(request.body.decode()) sku_id = json_dict.get('sku_id') count = json_dict.get('count') selected = json_dict.get('selected') # 验证 if not all([sku_id, count]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # sku_id有效 try: sku = SKU.objects.get(pk=sku_id) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '商品编号无效' }) # 数量 count = int(count) if count > 5: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '购买数量不能超过5个' }) elif count < 1: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '购买数量不能少于1个' }) elif count > sku.stock: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '商品库存不足' }) # 选中状态 # if selected == 'true': # selected = True # else: # selected = False # 处理、响应 response = http.JsonResponse({ 'code': RETCODE.OK, 'errmsg': 'OK', 'cart_sku': { 'id': sku.id, 'selected': str(selected), 'default_image_url': sku.default_image.url, 'name': sku.name, 'price': str(sku.price), 'count': count, 'total_amount': str(count * sku.price) } }) if request.user.is_authenticated: # 登录状态,将购物车存入redis redis_cli = get_redis_connection('cart') # 向hash中存商品编号、数量 redis_cli.hset('cart%d' % request.user.id, sku_id, count) # 向set中存商品编号,表示选中此商品 if selected: redis_cli.sadd('selected%d' % request.user.id, sku_id) else: redis_cli.srem('selected%d' % request.user.id, sku_id) else: # 未登录,存入cookie # 1.读取cookie中的购物车数据 cart_str = request.COOKIES.get('cart') if cart_str: # 如果购物车数据已经存在,则转字典 cart_dict = meiduo_json.loads(cart_str) else: # 如果第一次加入购物车数据,则新建字典 cart_dict = {} # 2.向字典中添加或修改数据 # cart_dict = { # sku_id: { # 'count': count, # 'selected': True # } # } cart_dict[sku_id] = {'count': count, 'selected': selected} # 3.写cookie cart_str = meiduo_json.dumps(cart_dict) # cart_str = json.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) return response
def post(self, request): # 接收,post方式,没有表单 json_dict = json.loads(request.body.decode()) sku_id = json_dict.get('sku_id') count = json_dict.get('count') # 验证 if not all([sku_id, count]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # sku_id有效 try: sku = SKU.objects.get(pk=sku_id) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '商品编号无效' }) # 数量 count = int(count) if count > 5: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '购买数量不能超过5个' }) elif count < 1: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '购买数量不能少于1个' }) elif count > sku.stock: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '商品库存不足' }) # 处理、响应 response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'}) username = request.COOKIES.get('username') if username: # 登录状态,将购物车存入redis redis_cli = get_redis_connection('cart') # 向hash中存商品编号、数量 redis_cli.hset('cart%d' % request.user.id, sku_id, count) # 向set中存商品编号,表示选中此商品 redis_cli.sadd('selected%d' % request.user.id, sku_id) else: # 未登录,存入cookie # 1.读取cookie中的购物车数据 cart_str = request.COOKIES.get('cart') if cart_str: # 如果购物车数据已经存在,则转字典 cart_dict = meiduo_json.loads(cart_str) else: # 如果第一次加入购物车数据,则新建字典 cart_dict = {} # 2.向字典中添加或修改数据 # cart_dict = { # sku_id: { # 'count': count, # 'selected': True # } # } cart_dict[sku_id] = {'count': count, 'selected': True} # 3.写cookie cart_str = meiduo_json.dumps(cart_dict) # cart_str = json.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) return response
def put(self, request): ''' 修改购物车中的数据json :param sku_id:库存商品编号 :param count:数量 :param selected:选中状态 ''' # 接收 param_dict = json.loads(request.body.decode()) sku_id = param_dict.get('sku_id') count = param_dict.get('count') selected = param_dict.get('selected', True) # 验证 # 非空,不要对bool类型进行验证 if not all([sku_id, count]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # 2.2库存商品编号有效 try: sku = SKU.objects.get(pk=sku_id, is_launched=True) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '库存商品编号无效' }) # 2.3数量 try: count = int(count) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '数量格式错误' }) if count <= 0: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '数量必须大于0' }) if count > sku.stock: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '超过库存' }) # 2.4选中状态 if not isinstance(selected, bool): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '选中状态无效' }) # 处理:修改 user = request.user response = http.JsonResponse({ 'code': RETCODE.OK, 'errmsg': 'ok', 'cart_sku': { 'id': sku.id, 'name': sku.name, 'default_image_url': sku.default_image.url, 'price': str(sku.price), 'count': count, 'selected': str(selected), 'total_amount': str(sku.price * count) } }) if user.is_authenticated: # 已登录,修改redis中的hash、set redis_cli = get_redis_connection('carts') redis_pl = redis_cli.pipeline() # 修改hash中的数量 redis_pl.hset('cart%d' % user.id, sku_id, count) # 修改set的选中状态 if selected: redis_pl.sadd('selected%d' % user.id, sku_id) else: redis_pl.srem('selected%d' % user.id, sku_id) redis_pl.execute() else: # 未登录,修改cookie # 1.读取cookie中购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is None: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '当前没有购物车数据' }) cart_dict = meiduo_json.loads(cart_str) # 2.修改 cart_dict[sku_id] = {'count': count, 'selected': selected} # 3.写cookie response.set_cookie('cart', meiduo_json.dumps(cart_dict), max_age=constants.CART_EXPIRES) # 响应 return response
def post(self, request): ''' 加入购物车,json参数 :param sku_id:库存商品编号 :param count:数量 ''' # 1.接收 param_dict = json.loads(request.body.decode()) sku_id = param_dict.get('sku_id') count = param_dict.get('count') # 2.验证 # 2.1非空 if not all([sku_id, count]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # 2.2库存商品编号有效 try: sku = SKU.objects.get(pk=sku_id, is_launched=True) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '库存商品编号无效' }) # 2.3数量 try: count = int(count) except: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '数量格式错误' }) if count <= 0: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '数量必须大于0' }) if count > sku.stock: return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '超过库存' }) # 3.处理 user = request.user response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'}) if user.is_authenticated: # 已登录,将信息保存在redis中 redis_cli = get_redis_connection('carts') redis_pl = redis_cli.pipeline() # 向hash中添加库存商品编号、数量 redis_pl.hset('cart%d' % user.id, sku_id, count) # 向set中添加库存商品编号,表示选中这个商品 redis_pl.sadd('selected%d' % user.id, sku_id) # 执行交互 redis_pl.execute() else: # 未登录,将信息保存在cookie中 # 1.读取cookie中购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is None: # 第一次向购物车中添加商品数据 cart_dict = {} else: # cookie中已有购物车数据,转换成字典 cart_dict = meiduo_json.loads(cart_str) # 2.向购物车中添加数据 cart_dict[sku_id] = {'count': count, 'selected': True} # 3.将购物车数据写入cookie中 response.set_cookie('cart', meiduo_json.dumps(cart_dict), max_age=constants.CART_EXPIRES) # 4.响应 return response