def get_proxy_list(self, num=1): # 当前系统时间 now = datetime.datetime.now() # 待返回的代理列表 res = list() balance_url = "http://ty-http-d.upupfile.com/index/index/get_my_pack_info?" \ "neek=525535&appkey=1ecf62d62c0b4fa31ce1d9e22070a1ea" headers = {"User-Agent": random.choice(settings.USER_AGENTS)} try: response = requests.get(balance_url, headers=headers) if response.status_code == 200: balance_data = myjson.loads(response.text) if balance_data.get("code") == 0: balance_list = balance_data.get("data") except: return res try: for item in balance_list: pack = item["pack"] balance = item["balance"] if balance < num: # 总额不够,则全部取 temp_num = balance else: # 总额有的多,则取差额 temp_num = num if not temp_num or now > datetime.datetime.fromtimestamp( item["near_fill_time"]): # 数量为0,或者已经过期,跳过下面直接执行下一次循环 continue ip_url = "http://http.tiqu.qingjuhe.cn/getip?" \ "num={}&type=2&pack={}&port=11&ts=1&lb=1&pb=4®ions=".format(temp_num, pack) response = requests.get(ip_url, headers=headers) if response.status_code == 200: json_data = myjson.loads(response.text) if json_data.get("code") == 0: res.extend(json_data.get("data")) num = num - temp_num if num <= 0: # 已经取够了 return except: pass finally: return res
def get_proxy_direct(self): """ 获取单个ip代理 :return: """ for one in redis_conn.sscan_iter(self.redis_set_key): # 当前系统时间 now = datetime.datetime.now() # 转json item = myjson.loads(one) expire_time = datetime.datetime.strptime(item["expire_time"], "%Y-%m-%d %H:%M:%S") if now > expire_time: # 过期了 redis_conn.srem(self.redis_set_key, one) continue # 拼接代理 temp = "http://{}:{}".format(item.get("ip"), item.get("port")) # 检测代理有效性 if self.is_proxy_valid(temp): return {self.proxy_type: temp} data = self.get_proxy_list(1) for item in data: temp = "http://{}:{}".format(item.get("ip"), item.get("port")) if self.is_proxy_valid(temp): redis_conn.sadd(self.redis_set_key, myjson.dumps(item)) return {self.proxy_type: temp}
def get(self, url="", **kwargs): """ 微博请求 :param url: 路由 :param kwargs: 其他参数 :return: """ # 判断url是否为空 if not url: return # 添加cookie if kwargs.get("cookies") and isinstance(kwargs.get("cookies"), str): kwargs["cookies"] = func.get_cookie_jar(kwargs.get("cookies", "")) # 添加headers if kwargs.get("headers") and isinstance(kwargs.get("headers"), str): kwargs["headers"] = myjson.loads(kwargs.get("headers")) params = dict() temp = url.split("?") url_after = url.split("?")[0] if len(temp) == 2: for key_value in temp[1].split("&"): key = key_value.split("=")[0] value = key_value.split("=")[1] params[key] = value return self.req_session.get(url_after, params=params, timeout=5, **kwargs)
def delete(self, request): try: user = request.user except: user = None serializer = serializers.CartDeleteSerializer( data=request.data) # 返回解析之后请求体的数据 serializer.is_valid(raise_exception=True) sku_id = serializer.validated_data['sku_id'] response = Response(status=204) if user is None: # 读取cookie cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) # 删除 if sku_id in cart_dict: del cart_dict[sku_id] # 保存到cookie中 cart_str = myjson.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) else: # 连接redis redis_cli = get_redis_connection('cart') # 构造键, 因为服务器会存入多个用户购物车信息, 通过用户编号可以区分 key = 'cart_%d' % request.user.id key_select = 'cart_selected_%d' % request.user.id # hash redis_cli.hdel(key, sku_id) # set redis_cli.srem(key_select, sku_id) return response
def put(self, request): try: user = request.user except: user = None serializer = serializers.CartSelectSerializer(data=request.data) serializer.is_valid(raise_exception=True) selected = serializer.validated_data['selected'] response = Response({'message': 'OK'}) if user is None: """Cookie""" cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) for key in cart_dict.keys(): cart_dict[key]['selected'] = selected cart_str = myjson.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) else: """Redis版""" # 连接redis redis_cli = get_redis_connection('cart') # 构造键, 因为服务器会存入多个用户信息的购物车信息, 通过用户编号可以区分 key = 'cart_%d' % request.user.id key_select = 'cart_selected_%d' % request.user.id # 获取所有商品编号, hash sku_ids = redis_cli.hkeys(key) # 选中 if selected: redis_cli.sadd(key_select, *sku_ids) else: redis_cli.srem(key_select, *sku_ids) return response
def ip_limit(self, target_ip="", banned_time=3600, select=True): """ ip限制 :param target_ip:目标ip :param banned_time: 封禁时长(单位为秒) :param select: True:查看是否被封禁;False:添加/修改封禁ip :return: select为True,查看target_ip是否被封禁,是:True,否:False;select为False,返回None """ conn = self.cache.conn banned_ip_sets = settings.REDIS_KEYS["banned_ip_sets"] for item in conn.sscan_iter(banned_ip_sets): if isinstance(item, bytes): temp = bytes.decode(item) ip_dict = myjson.loads(temp) if ip_dict.get("unban_time") < time.time(): # 已经过了解封时间了,解封该ip conn.srem(banned_ip_sets, temp) else: # 没有过解封时间,比较是否有该ip # 查询ip是否被封 if ip_dict.get("ip", "") == target_ip: if select: return True else: conn.srem(banned_ip_sets, temp) else: if select: return False else: # 重新添加新值 item = myjson.dumps( dict(ip=target_ip, unban_time=time.time() + banned_time)) conn.sadd(banned_ip_sets, item)
def delete(self, request): """ 删除购物车信息 :param request: request.data中有sku_id :return: 无, 有状态码 """ # 获取当前用户信息(并验证登陆) try: user = request.user except Exception: # 验证失败,用户数据为空 user = None delete_serializer = DeleteCartSerializer(data=request.data) if delete_serializer.is_valid(raise_exception=True) is False: return Response(delete_serializer.errors) # 获取属性的值 sku_id = delete_serializer.validated_data['sku_id'] # 用户已登录,从redis中删除 if user is not None and user.is_authenticated: redis_conn = get_redis_connection('cart') # 删除商品数量信息 redis_conn.hdel('cart_%s' % user.id, sku_id) # 删除商品勾选信息 redis_conn.srem('cart_selected_%s' % user.id, sku_id) response = Response(status=status.HTTP_204_NO_CONTENT) return response # 用户未登录,从cookie中删除 else: # 获取请求中的cookie中的购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is not None: # 不为空,将其解码并反序列化为python类型 cart_dict = myjson.loads(cart_str) # 判断购物车数据列表中是否有该商品id,有则删除该键 if sku_id in cart_dict: del cart_dict[sku_id] # 将cookie数据序列化为bytes类型并编码 cookie_cart = myjson.dumps(cart_dict) # 设置响应数据 response = Response(status=status.HTTP_204_NO_CONTENT) # 设置购物车的cookie # 需要设置有效期,否则是临时cookie response.set_cookie('cart', cookie_cart, max_age=constants.CART_COOKIE_EXPIRES) return response else: # 购物车数据为空,则无数据可删除,直接返回 response = Response(status=status.HTTP_204_NO_CONTENT) return response
def post(self, request): # 获取数据 # 序列化器先反序列化校验一波 serializer = serializers.CartAddSerializer(data=request.data) serializer.is_valid(raise_exception=True) # 获取校验过的数据 sku_id = serializer.validated_data['sku_id'] count = serializer.validated_data['count'] # 创建对象是反序列化,用validated_data, 序列化才用data response = Response(serializer.validated_data) try: # 如果用户认证信息不存在则抛异常 user = request.user except: user = None # 判断用户是否登录 if user is None: # 如果没有登录就存在cookie # 先读cookie原有的数据 cart_str = request.COOKIES.get('cart') # 添加新的商品要在原有的cookie上面添加,如果原来没有就弄一个{}再添加 if cart_str is None: cart_dict = {} else: cart_dict = myjson.loads(cart_str) # 修改cookie cart_dict[sku_id] = { "count": count, "selected": True } # 写cookie # 字典转成字符串 cart_str = myjson.dumps(cart_dict) # 写cookie response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) else: # 如果登录就存进redis # 连接redis redis_cli = get_redis_connection('cart') # 拼接一下key key = 'cart_%d'%user.id keyselect = 'cart_select_%d'%user.id # 存redis redis_cli.hset(key, sku_id, count) redis_cli.sadd(keyselect, sku_id) # 返回序列化后的数据 return response
def get(self, request): """ 获取购物车信息 请求方式 : GET /cart/ :param request: request.user 当前用户 :return: id, count, selected, name, default_image_url, price 也就是商品的各个数据 """ # 获取用户, 判断用户登录 try: user = request.user except Exception: user = None if user is not None and user.is_authenticated: # 用户登录,数据从redis中取出 redis_conn = get_redis_connection('cart') # 获取redis中存储的信息 redis_cart_id = redis_conn.hkeys('cart_%s' % user.id) redis_cart_selected = redis_conn.smembers('cart_selected_%s' % user.id) print(redis_cart_selected) redis_cart_selected = [int(sku_id) for sku_id in redis_cart_selected] print(redis_cart_selected) # 查询商品 skus = SKU.objects.filter(pk__in=redis_cart_id) # 为商品添加额外两个属性 for sku in skus: sku.count = redis_conn.hget('cart_%s' % user.id, sku.id) sku.selected = sku.id in redis_cart_selected # 在,则为True,不在则为False else: # 用户未登录,从cookie中读取 cart_str = request.COOKIES.get('cart') if cart_str is not None: cart_dict = myjson.loads(cart_str) else: cart_dict = {} # 遍历处理购物车数据 # 根据键,查询商品信息 skus = [] for key, value in cart_dict.items(): sku = SKU.objects.get(pk=key) sku.count = value['count'] sku.selected = value['selected'] skus.append(sku) # 序列化数据并返回 find_serializer = FindCartSerializer(skus, many=True) return Response(find_serializer.data)
def post(self, request): # 判断用户是否登录 try: # 如果用户认证信息不存在则抛异常 user = request.user except: user = None # 接收请求数据, 进行验证 serializer = serializers.CartAddSerializer(data=request.data) serializer.is_valid(raise_exception=True) # 验证通过后获取数据 sku_id = serializer.validated_data['sku_id'] count = serializer.validated_data['count'] # 构造响应对象 response = Response(serializer.validated_data) if user is None: """Cookie""" # 如果未登录, 则存入cookie # 读取cookie中的数据 cart_str = request.COOKIES.get('cart') if cart_str is None: cart_dict = {} else: cart_dict = myjson.loads(cart_str) # 取出原数量 if sku_id in cart_dict: count_cart = cart_dict[sku_id]['count'] else: count_cart = 0 # 修改数据 cart_dict[sku_id] = {'count': count + count_cart, 'selected': True} # 写cookie cart_str = myjson.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) else: """Redis""" # 如果已登录, 则存入redis # 连接redis redis_cli = get_redis_connection('cart') # 构造键, 因为服务器会存多个用户的购物车信息, 通过用户编号可以区分 key = 'cart_%d' % request.user.id key_select = 'cart_selected_%d' % request.user.id # 将商品编号 数量存入hash中 redis_cli.hset(key, sku_id, count) # 将商品编号存入set中,表示选中此是商品 redis_cli.sadd(key_select, sku_id) return response
def get(self, request): # 查询数据 try: user = request.user except: user = None if user is None: # 先获取cookie cart_str = request.COOKIES.get('cart') # 把cookie转成字典 cart_dict = myjson.loads(cart_str) # 遍历cookie的keys skus = [] for key, value in cart_dict.items(): sku = SKU.objects.get(pk=key) sku.count = value['count'] sku.selected = value['selected'] skus.append(sku) serializer = serializers.CartSerializer(skus, many=True) return Response(serializer.data) else: # 存redis # 连接redis redis_cli = get_redis_connection('cart') key = 'cart_%d'%user.id keyselect = 'cart_select_%d'%user.id # 从hash中读取所有商品编号 sku_ids = redis_cli.hkeys(key) # 从set中取出所有sku_id sku_ids_selected = redis_cli.smembers(keyselect) # 强转redis里面取出来的byte类型为int类型,不然sku.id不会和这个列表里面的值相等,因为类型就不一致 sku_ids_selected = [int(skuid_selected) for skuid_selected in sku_ids_selected] # 查出哈希表里面全部sku的id skus = SKU.objects.filter(id__in=sku_ids) # 查出所有sku然后新增两个属性,然后再用序列化器序列化输出 for sku in skus: sku.count = redis_cli.hget(key, sku.id) sku.selected = sku.id in sku_ids_selected serializer = serializers.CartSerializer(skus, many=True) return Response(serializer.data)
def resp_convert(self, response, loadpage=False): # 定义要返回的数据 res = {"status": False} if loadpage: pattern1 = "location.replace\(\"(.*?)\"\)" pattern2 = "location.replace\(\"(.*?)\"\)" url_list = re.findall(pattern1, response.text) or re.findall( pattern2, response.text) if url_list: # 重定向 url = url_list[0] if url.find("login.sina.com") >= 0: # 微博未登录,重定向到微博登录页面 res["code"] = settings.WEIBO_NOT_LOGIN else: # 普通的重定向 res["code"] = 302 else: res["status"] = True else: if response.status_code == 200: try: temp_res = myjson.loads(response.text) code = temp_res.get("code", "") if not code: # code为空,则去msg中找错误码 err_code = re.search(r'\d+', temp_res.get("msg")).group() or "" res.update(code=err_code) else: if code == "100000": # 成功 res["status"] = True res.update(code=code) res.update(reason=temp_res.get("msg", "")) except Exception: # 返回内容为非json格式,则肯定是出错了 res.update(reason="response返回结果为非json格式") if response.url == 'https://weibo.com/sorry?pagenotfound': # 报页面找不到,说明是账号异常 res.update( code=settings.WEIBO_ERROR_CODE_PAGE_NOT_FOUND) else: # 默认返回失败 res.update(reason="返回非200") return res
def receiver_callback(self, channel, method, properties, body): try: print("[{}.receiver_callback]: 接收到了消息,消息内容为:{}".format( self.__class__.__name__, body)) # 将消息转化为字典格式 msg = myjson.loads(body.decode("utf-8")) # 执行点赞脚本 weibo_worker.do_script(msg) if not self.no_ack: # no_ack为True,显式给rabbitmq发送一个消息确认 channel.basic_ack(delivery_tag=method.delivery_tag) except Exception as ex: print("[{}.receiver_callback]: raise exception,ex={}".format( self.__class__.__name__, repr(ex))) pass
def get(self,request): try: user = request.user except: user = None if user is None: # 未登录,读cookie # 获取cookie中购物车信息 cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) print(cart_dict) # 根据商品编号查询对象,并添加数量、选中属性 skus = [] for key,value in cart_dict.items(): sku = SKU.objects.get(pk=key) sku.count = value['count'] sku.selected = value['selected'] skus.append(sku) # print(skus) # # 序列化输出 # serializer = serializers.CartSerializer(skus, many=True) # return Response(serializer.data) else: # 已登录,读redis # 连接redis redis_cli = get_redis_connection('cart') # 构造键,因为服务器会存多个用户的购物车信息,通过用户编号可以区分 key = 'cart_%d' % request.user.id key_select = 'cart_selected_%d' % request.user.id # 从hash中读取所有商品编号 sku_ids = redis_cli.hkeys(key) # 读取选中的商品编号 sku_ids_selected = redis_cli.smembers(key_select) sku_ids_selected = [int(sku_id) for sku_id in sku_ids_selected] # 查询商品 skus = SKU.objects.filter(pk__in = sku_ids) # 遍历商品,增加数量、选中属性 for sku in skus: sku.count = redis_cli.hget(key,sku.id) sku.selected = sku.id in sku_ids_selected # 序列化输出 serializer = serializers.CartSerializer(skus,many=True) # print(serializer.data) return Response(serializer.data)
def put(self, request): try: user = request.user except: user = None serializer = serializers.CartAddSerializer(data=request.data) serializer.is_valid(raise_exception=True) sku_id= serializer.validated_data['sku_id'] count = serializer.validated_data['count'] selected = serializer.validated_data['selected'] response = Response(serializer.data) # 判断user是否存在 if user is None: # 用cookie cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) cart_dict[sku_id] = { "count": count, "selected": selected } cart_str = myjson.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) else: # 用redis # 连接redis redis_cli = get_redis_connection('cart') key = 'cart_%d'%user.id keyselect = 'cart_select_%d'%user.id redis_cli.hset(key, sku_id, count) if selected: redis_cli.sadd(keyselect, sku_id) else: redis_cli.srem(keyselect, sku_id) return response
def put(self,request): try: user = request.user except: user = None # 接收数据并验证 serializer = serializers.CartAddSerializer(data=request.data) serializer.is_valid(raise_exception=True) # 验证通过后获取数据 sku_id =serializer.validated_data['sku_id'] count = serializer.validated_data['count'] selected = serializer.validated_data['selected'] response = Response(serializer.validated_data) if user is None: # 未登录,操作cookie # 1.读取 cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) #2.修改 cart_dict[sku_id] = { 'count':count, 'selected':selected } #保存 cart_str = myjson.dumps(cart_dict) response.set_cookie('cart',cart_str,max_age=constants.CART_COOKIE_EXPIRES) else: # 已登录,操作redis # 连接redis redis_cli = get_redis_connection('cart') # 构造键,因为服务器会存多个用户的购物车信息,通过用户编号可以区分 key = 'cart_%d' % request.user.id key_select = 'cart_selected_%d' % request.user.id #修改数量 redis_cli.hset(key,sku_id,count) #修改选中 if selected: redis_cli.sadd(key_select,sku_id) else: redis_cli.srem(key_select,sku_id) return response
def get_proxies_direct(self, num=1): """ 获取多个代理 :param num: :return: """ res = list() current_num = 0 for one in redis_conn.sscan_iter(self.redis_set_key): # 当前系统时间 now = datetime.datetime.now() # 转json item = myjson.loads(one) expire_time = datetime.datetime.strptime(item["expire_time"], "%Y-%m-%d %H:%M:%S") if now > expire_time: # 过期了 redis_conn.srem(self.redis_set_key, one) continue # 拼接代理 temp = "http://{}:{}".format(item.get("ip"), item.get("port")) # 检测代理有效性 if self.is_proxy_valid(temp): res.append({self.proxy_type: temp}) current_num += 1 if current_num >= num: break if current_num < num: data = self.get_proxy_list(num=(num - current_num)) for item in data: temp = "http://{}:{}".format(item.get("ip"), item.get("port")) if self.is_proxy_valid(temp): redis_conn.sadd(self.redis_set_key, myjson.dumps(item)) res.append({self.proxy_type: temp}) return res
def post(self, url="", **kwargs): """ 微博请求 :param url: 路由 :param kwargs: 其他参数 :return: """ # 判断url是否为空 if not url: return # 添加cookie if "cookies" in kwargs.keys(): kwargs["cookies"] = func.get_cookie_jar(kwargs.get("cookies", "")) # 添加headers if kwargs.get("headers") and isinstance(kwargs.get("headers"), str): kwargs["headers"] = myjson.loads(kwargs.get("headers")) return self.req_session.post(url, timeout=5, **kwargs)
def get_cookie_jar(cookies): """ 根据cookies的json字符串,来获取一个RequestsCookieJar对象 :param cookies: cookie的json字符串 :return:RequestsCookieJar对象 """ # 添加cookie if not cookies: # 如果cookies为空,则必定刷不成功,直接返回 return # 实例化cookiejar对象 cookie_jar = requests.cookies.RequestsCookieJar() # 遍历cookie列表,设置到cookiejar中 cookies = myjson.loads(cookies) for key, val in cookies.items(): cookie_jar.set(key, val) return cookie_jar
def merge_cookie_to_redis(request, user_id, response): """ 合并cookie购物车信息到redis 以cookie里面的数据为准 :param request: 请求对象,用来获取cookie :param user_id: 用来连接redis :param response: 用来返回删除cookie的操作 :return: """ # 获取cookie的数据 cart_str = request.COOKIES.get('cart_%d' % user_id) # 字符串转成字典 cart_dict = myjson.loads(cart_str) # 连接redis cart_key = 'cart_%d' % user_id cart_selected_key = 'cart_select_%d' % user_id redis_cli = get_redis_connection('cart') # 获取管道 redis_pl = redis_cli.pipeline() # 遍历cookie的数据然后添加到redis中 只修改redis中和cookie一致的商品,如果redis有其他商品而cookie没有,则不会有影响 for sku_id, sku_dict in cart_dict.items(): # 先存id和数量,以cookie为准,就是如果已经存在这个商品,它的数量会是现在这个,如果不存在就创建新的sku_id:count进去 redis_pl.hset(cart_key, sku_id, sku_dict['count']) # 看这个cookie的是否选中,选中就把redis改为选中,否则就不选中, if sku_dict['selected']: redis_pl.sadd(cart_selected_key, sku_id) else: redis_pl.srem(cart_selected_key, sku_id) # 执行管道命令 redis_pl.execute() # 删除cookie并返回包含这个操作的响应对象 response.set_cookie('cart', '', max_age=0) # 返回这个response return response
def put(self, request): try: user = request.user except: user = None # 获取, 校验数据, 并构建一个响应对象 serializer = serializers.CartSelectSerializer(data=request.data) serializer.is_valid(raise_exception=True) selected = serializer.validated_data['selected'] response = Response(serializer.validated_data) # 未登录的情况 if user is None: cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) for key in cart_dict.keys(): cart_dict[key]['selected'] = selected cart_str = myjson.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) # 登录的情况 else: # 连接redis redis_cli = get_redis_connection('cart') key = 'cart_%d'%user.id keyselect = 'cart_select_%d'%user.id sku_ids = redis_cli.hkeys(key) if selected: redis_cli.sadd(keyselect, *sku_ids) else: redis_cli.srem(keyselect, *sku_ids) return response
def delete(self, request): try: user = request.user except: user = None serializer = serializers.CartDeleteSerializer(data=request.data) serializer.is_valid(raise_exception=True) sku_id = serializer.validated_data['sku_id'] response = Response(status=204) if user is None: cart_str = request.COOKIES.get('cart') cart_dict = myjson.loads(cart_str) if sku_id in cart_dict: del cart_dict[sku_id] # 写cookie cart_str = myjson.dumps(cart_dict) response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES) else: # 写redis # 连接redis redis_cli = get_redis_connection('cart') key = 'cart_%d'%user.id keyselect = 'cart_select_%d'%user.id redis_cli.hdel(key, sku_id) redis_cli.srem(keyselect, sku_id) return response
def merge_cookie_to_redis(request, user_id, response): """ 以cookie中的商品数据为准, 如果redis中也有这个商品,则覆盖 将cookie中的购物车信息,添加redis中,此方法供登录时调用 :param request: 请求对象, 用于读取cookie中的购物车信息 :param user_id: 用户编号, 用于操作redis中的购物车数据,构成键 :param response: 响应对象,删除cookie购物车数据 :return: 响应对象,包含了删除cookie的操作 """ # 1.读取cookie中的购物车数据 cart_str = request.COOKIES.get('cart') # 如果cookie中没有购物车信息,则直接返回 if cart_str is None: return response # 将字符串转成字典 cart_dict = myjson.loads(cart_str) # 2.遍历,写入redis中 # 获取redis连接 redis_cli = get_redis_connection('cart') # 构造键 key_cart = 'cart_%d' % user_id key_selected = 'cart_selected_%d' % user_id # 获取管道 redis_pipeline = redis_cli.pipeline() for sku_id, sku_dict in cart_dict.items(): # hash存商品编号 数量 redis_pipeline.hset(key_cart, sku_id, sku_dict['count']) # set根据选中状态存商品编号 if sku_dict['selected']: redis_pipeline.sadd(key_selected, sku_id) else: redis_pipeline.srem(key_selected, sku_id) # 执行管道中的命令 redis_pipeline.execute() # 3.删除cookie中的购物车数据 response.set_cookie('cart', '', max_age=0) return response
def merge_cookie_to_redis(request, user_id, response): ''' 以cookie中的商品数据为准,如果redis中也有这个商品,则无视 将cookie中的购物车信息,添加到redis中,此方法供登录时调用 :param request: 请求对象,用于读取cookie中的购物车信息 :param user_id: 用户编号,用于操作redis中的购物车数据,构成键 :param response: 响应对象,删除cookie中购物车数据 :return: 响应对象,包含了删除cookie的操作 ''' # 1.读取cookie中的购物车数据 cart_str = request.COOKIES.get('cart') # 如果cookie中没有购物车信息,则直接返回 if cart_str is None: return response # 将字符串转字典 cart_dict = myjson.loads(cart_str) # 2.遍历,写入redis中 # 获取redis连接 redis_cli = get_redis_connection('cart') key_cart = 'cart_%d' % user_id key_selected = 'cart_selected_%d' % user_id # 获取管道 redis_pipeline = redis_cli.pipeline() for sku_id, sku_dict in cart_dict.items(): # hash存商品编号、数量 redis_pipeline.hset(key_cart, sku_id, sku_dict['count']) # set根据选中状态存商品编号 if sku_dict['selected']: redis_pipeline.sadd(key_selected, sku_id) else: redis_pipeline.srem(key_selected, sku_id) # 执行管道中的命令 redis_pipeline.execute() # 3.删除cookie中的购物车数据 response.set_cookie('cart', '', max_age=0) return response
def post(self,request): """ 购物车增加商品 """ """ 1.判断用户是否登录 2.获取用户 2.1如果用户认证信息不存在则抛异常 2.2接收请求数据,进行验证 2.3验证通过后获取数据 2.4构造响应对象 3.登录与未登录 3.1.用户未登录 # 如果未登录,则存入cookie # 读取cookies中的数据 # 取出原数量 # 修改数据 # 写cookie 3.2.用户登录 # 如果已登录,则存入redis # 连接redis # 构造键,因为服务器会存多个用户的购物车信息,通过用户编号可以区分 # 将商品编号、数量存入hash中 # 将商品编号存入set中,表示选中此商品 """ # 1.判断用户是否登录 try: #如果用户认证信息不存在则抛异常 user = request.user except: user = None #接收请求数据,进行验证 # 在序列化器中传入数据 serialzier = serializers.CartAddSerializer(data=request.data) #验证序列化器 serialzier.is_valid(raise_exception=True) # 验证通过后从请求中获取数据 sku_id = serialzier.validated_data['sku_id'] count = serialzier.validated_data['count'] #构建响应对象 response = Response(serialzier.validated_data) if user is None: # 如果未登录,则存入cookie # 读取cookies中的数据 cart_str = request.COOKIES.get('cart') if cart_str is None: cart_dict = {} else: cart_dict = myjson.loads(cart_str) # #取出原数量 # if sku_id in cart_dict: # count_cart = cart_dict[sku_id]['count'] # else: # count_cart = 0 #修改数据 cart_dict[sku_id] = { "count":count, 'selected':True } #写cookie,字典转字符串 cart_str = myjson.dumps(cart_dict) response.set_cookie('cart',cart_str,max_age=constants.CART_COOKIE_EXPIRES) # set_cookie(键,值,过期时长) else: # 如果已登录,则存入redis # 连接redis redis_cli = get_redis_connection('cart') # 构造键,因为服务器会存多个用户的购物车信息,通过用户编号可以区分 key = 'cart_%d'%request.user.id key_select = 'cart_selected_%d'%request.user.id #将商品编号,数量存入hash中 redis_cli.hset(key,sku_id,count) # 将商品编号存入set中,表示选中此商品 redis_cli.sadd(key_select,sku_id) # key,key_select都作为键被设置进去 return response
def merge_cart_cookie_to_redis(request, user_id, response): """ 合并购物车数据到redis中 :param request: 用于读取cookie信息 :param user: 当前登陆用户 :param response: 响应对象,清除cookie数据 :return: """ # 获取cookie中购物车信息 cart_str = request.COOKIES.get("cart") # 若为空,则直接返回响应 if not cart_str: return response # 拿到字典类型的cookie中购物车数据 cookie_cart_dict = myjson.loads(cart_str) # 定义字典,用于向redis中保存数据 redis_cart_dict = {} # 记录redis勾选状态的sku_id redis_cart_selected_add = [] # 添加sku_id列表 redis_cart_selected_remove = [] # 删除sku_id列表 # 获取redis连接 redis_conn = get_redis_connection("cart") redis_pip = redis_conn.pipeline() # 合并cookie购物车与redis购物车,保存到redis_cart_dict字典中 for sku_id, count_select_dict in cookie_cart_dict.items(): """ cookie中数据保存格式 { sku_id: { "count": xxx, // 数量 "selected": True // 是否勾选 }, ... } """ # 处理商品数量 redis_cart_dict[sku_id] = count_select_dict['count'] # 处理勾选状态,若勾选,则向添加列表中添加sku_id,反之则向删除列表中添加sku_id if count_select_dict['selected']: redis_cart_selected_add.append(sku_id) else: redis_cart_selected_remove.append(sku_id) # 如果添加完以后redis_cart_dict中有数据,则向redis中存储 if redis_cart_dict: redis_pip.hmset('cart_%s' % user_id, redis_cart_dict) if redis_cart_selected_add: redis_pip.sadd('cart_selected_%s' % user_id, *redis_cart_selected_add) if redis_cart_selected_remove: redis_pip.srem('cart_selected_%s' % user_id, *redis_cart_selected_remove) redis_pip.execute() # 删除cookie中存储的信息 # response.delete_cookie('cart') response.set_cookie('cart', 0, max_age=0) return response
def post(self, request): """ 添加购物车信息 请求方式: POST /cart/ :param request: request.data中包含sku_id(商品sku id), count(数量), selected(是否勾选,默认勾选) :return: sku_id, count, selected """ # 获取当前用户信息(并验证登陆) try: user = request.user except Exception: # 验证失败,用户数据为空 user = None # 定义序列化器对象,并验证 cart_serializer = AddCartSerializer(data=request.data) cart_serializer.is_valid(raise_exception=True) # 获取属性的值 sku_id = cart_serializer.validated_data.get('sku_id') count = cart_serializer.validated_data.get('count') selected = cart_serializer.validated_data.get('selected') response = Response(cart_serializer.data, status=status.HTTP_201_CREATED) # 若用户不为空且已登录 if user is not None and user.is_authenticated: # 用户登录,将数据保存到redis中 redis_conn = get_redis_connection('cart') # 使用hash记录购物车商品数量 redis_conn.hset('cart_%s' % user.id, sku_id, count) # 使用set记录是否勾选 if selected: # 默认勾选 redis_conn.sadd('cart_selected_%s' % user.id, sku_id) # 用户未登录,将数据保存到cookie中 else: """ cookie中数据保存格式 { sku_id: { "count": xxx, // 数量 "selected": True // 是否勾选 }, ... } """ # 获取请求中的cookie中的购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is not None: # 不为空,将其解码并反序列化为python类型 cart_dict = myjson.loads(cart_str) else: # 为空,返回空字典 cart_dict = {} # 将数据以正确的格式添加 cart_dict[sku_id] = { 'count': count, 'selected': selected } # 将cookie数据序列化为bytes类型并编码 cookie_cart = myjson.dumps(cart_dict) # 设置购物车的cookie # 需要设置有效期,否则是临时cookie response.set_cookie('cart', cookie_cart, max_age=constants.CART_COOKIE_EXPIRES) return response
def put(self, request): """ 购物车全选 PUT /cart/selection/ :param request: request.data中有selected(是否全选) :return: {"message": "ok"} """ # 获取当前用户信息(并验证登陆) try: user = request.user except Exception: # 验证失败,用户数据为空 user = None selall_serializer = SelectAllCartSerializer(data=request.data) selall_serializer.is_valid(raise_exception=True) # 获取属性的值 selected = selall_serializer.validated_data['selected'] if user is not None and user.is_authenticated: # 用户已登陆, 数据在redis中 redis_conn = get_redis_connection('cart') # 获取所有商品sku_id sku_ids = redis_conn.hkeys('cart_%d' % request.user.id) # 判断是否全选 if selected: # 全选 redis_conn.sadd('cart_selected_%s' % user.id, *sku_ids) else: # 取消全选 redis_conn.srem('cart_selected_%s' % user.id, *sku_ids) response = Response({'message': 'ok'}) return response else: # 用户未登录,从cookie中删除 # 获取请求中的cookie中的购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is not None: # 不为空,将其解码并反序列化为python类型 cart_dict = myjson.loads(cart_str) # 获取商品id sku_id,修改勾选属性值为请求中的值 for sku_id in cart_dict: cart_dict[sku_id]['selected'] = selected # 将cookie数据序列化为bytes类型并编码 cookie_cart = myjson.dumps(cart_dict) # 设置响应数据 response = Response({'message': 'OK'}) # 设置购物车的cookie # 需要设置有效期,否则是临时cookie response.set_cookie('cart', cookie_cart, max_age=constants.CART_COOKIE_EXPIRES) return response else: # 购物车数据为空,则无数据可删除,直接返回 response = Response({'message': 'OK'}) return response
def put(self, request): """ 修改购物车信息 请求方式 : PUT /cart/ :param request: sku_id(商品sku id), count(数量), selected(是否勾选,默认勾选) :return: sku_id, count, selected """ # 获取当前用户信息(并验证登陆) try: user = request.user except Exception: # 验证失败,用户数据为空 user = None update_serializer = UpDateCartSerializer(data=request.data) update_serializer.is_valid(raise_exception=True) # 获取属性的值 sku_id = update_serializer.validated_data.get('sku_id') count = update_serializer.validated_data.get('count') selected = update_serializer.validated_data.get('selected') response = Response(update_serializer.data) # 用户已登录,数据在redis中 if user is not None and user.is_authenticated: redis_conn = get_redis_connection('cart') # 修改商品数量信息 redis_conn.hset('cart_%s' % user.id, sku_id, count) # 修改商品是否勾选 if selected is True: # 未勾选, 修改为勾选 redis_conn.sadd('cart_selected_%s' % user.id, sku_id) else: # 已勾选, 修改为未勾选 redis_conn.srem('cart_selected_%s' % user.id, sku_id) # 用户未登录,数据在cookie中 else: # 获取请求中的cookie中的购物车数据 cart_str = request.COOKIES.get('cart') if cart_str is not None: # 不为空,将其解码并反序列化为python类型 cart_dict = myjson.loads(cart_str) else: # 为空,返回空字典 cart_dict = {} cart_dict[sku_id] = { 'count': count, 'selected': selected } # 将cookie数据序列化为bytes类型并编码 cookie_cart = myjson.dumps(cart_dict) # 设置购物车的cookie # 需要设置有效期,否则是临时cookie response.set_cookie('cart', cookie_cart, max_age=constants.CART_COOKIE_EXPIRES) return response