Пример #1
0
    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&regions=".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
Пример #2
0
    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}
Пример #3
0
    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)
Пример #4
0
 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
Пример #5
0
 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
Пример #6
0
    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)
Пример #7
0
    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
Пример #8
0
    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
Пример #9
0
    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)
Пример #10
0
    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
Пример #11
0
    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)
Пример #12
0
    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
Пример #13
0
    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
Пример #14
0
    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)
Пример #15
0
    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
Пример #16
0
    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
Пример #17
0
    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
Пример #18
0
    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)
Пример #19
0
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
Пример #20
0
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
Пример #21
0
    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
Пример #22
0
    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
Пример #23
0
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
Пример #24
0
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
Пример #25
0
    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
Пример #26
0
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
Пример #27
0
    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
Пример #28
0
    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
Пример #29
0
    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