Example #1
0
    def handle(self, **options):
        if (not options['flush_rqdata'] and
            not options['flush_lru'] and
            not options['flush_django_cache'] and
            not options['flush_all']):
            raise CommandError("No options were provided. Use one of "
                               "--django-cache, --rqdata, --lru "
                               "or --all.")

        self.stdout.write('Flushing cache...')

        if options['flush_rqdata'] or options['flush_all']:
            # Flush all rq data, dirty counter and restore Pootle revision
            # value.
            r_con = get_redis_connection('redis')
            r_con.flushdb()
            self.stdout.write('RQ data removed.')
            Revision.set(Unit.max_revision())
            self.stdout.write('Max unit revision restored.')

        if options['flush_django_cache'] or options['flush_all']:
            r_con = get_redis_connection('default')
            r_con.flushdb()
            self.stdout.write('All default Django cache data removed.')

        if options['flush_lru'] or options['flush_all']:
            r_con = get_redis_connection('lru')
            r_con.flushdb()
            self.stdout.write('All lru cache data removed.')
    def handle(self, *args, **options):
        if options["all"]:
            if args:
                raise CommandError("cannot use --all with a cache name")

            args = settings.CACHES.keys()
        else:
            if not args:
                raise CommandError("specify at least one cache to clear")

            # Make sure all names given exist
            for name in args:
                get_cache(name)

        method = options["method"]
        noop = options["noop"]

        action = "Clearing " if not noop else "Not clearing "

        if method == "conservative":
            for name in args:
                config = settings.CACHES[name]
                backend = config["BACKEND"]
                failed = False
                if backend.startswith("django_redis."):
                    try:
                        import django_redis
                        django_redis.get_redis_connection(name)
                        # Yes, we grab all exceptions. It is up to the
                        # user to diagnose how their configuration is
                        # wrong.
                    except:  # pylint: disable=bare-except
                        failed = True
                else:
                    failed = True

                if failed:
                    raise CommandError(
                        "clearcache does not know how to "
                        "conservatively clear a "
                        "cache with backend {0}".format(backend))

            for name in args:
                self.stdout.write(action + name)
                config = settings.CACHES[name]
                cache = get_cache(name)
                prefix = cache.key_prefix
                backend = config["BACKEND"]
                if backend.startswith("django_redis."):
                    import django_redis
                    con = django_redis.get_redis_connection(name)
                    keys = con.keys(prefix + ':*')
                    if keys and not noop:
                        con.delete(*keys)
        else:
            for name in args:
                self.stdout.write(action + name)
                cache = get_cache(name)
                if not noop:
                    cache.clear()
Example #3
0
    def test_is_amendment(self):
        config['motions_amendments_enabled'] = True
        get_redis_connection('default').flushall()
        amendment = Motion.objects.create(title='amendment', parent=self.motion)

        self.assertTrue(amendment.is_amendment())
        self.assertFalse(self.motion.is_amendment())
Example #4
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 1 requests to see if anonymous is enabled and get all config values
     """
     get_redis_connection("default").flushall()
     with self.assertNumQueries(1):
         self.client.get(reverse('config-list'))
Example #5
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 1 requests to see if anonyomus is enabled
     * 1 requests to get the list of all projectors,
     """
     get_redis_connection("default").flushall()
     with self.assertNumQueries(2):
         self.client.get(reverse('tag-list'))
Example #6
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 1 requests to find out if anonymous is enabled
     * 2 request to get the list of all groups and
     """
     get_redis_connection('default').flushall()
     with self.assertNumQueries(3):
         self.client.get(reverse('group-list'))
Example #7
0
    def tearDown(self):
        settings.MEDIA_ROOT = self._media_org
        shutil.rmtree(self._media_tmp)

        # wipe cache -- see https://niwinz.github.io/django-redis/latest/#_testing_with_django_redis
        from django_redis import get_redis_connection
        get_redis_connection("default").flushall()

        return super(ApiResourceTestCaseMixin, self).tearDown()
Example #8
0
def clear_cache(request):
    """Currently tests only use one cache so this clears all"""

    from django.core.cache import caches

    from django_redis import get_redis_connection

    get_redis_connection('default').flushdb()
    caches["exports"].clear()
Example #9
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 3 requests to get the permission for anonymous and
     * 1 requests to get the list of all projectors.
     """
     get_redis_connection('default').flushall()
     with self.assertNumQueries(4):
         self.client.get(reverse('mediafile-list'))
Example #10
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 3 requests to get the permission for anonymous,
     * 1 requests to get the list of all projectors,
     * 1 request to get the list of the projector defaults and
     """
     get_redis_connection("default").flushall()
     with self.assertNumQueries(5):
         self.client.get(reverse('projector-list'))
Example #11
0
 def test_admin(self):
     """
     Tests that only the following db queries are done:
     * 5 requests to get the session an the request user with its permissions,
     * 1 requests to get the list of all tags,
     """
     self.client.force_login(User.objects.get(pk=1))
     get_redis_connection("default").flushall()
     with self.assertNumQueries(6):
         self.client.get(reverse('tag-list'))
Example #12
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 3 requests to get the permission for anonymous,
     * 1 requests to get the list of all users and
     * 2 request to get all groups (needed by the user serializer).
     """
     get_redis_connection('default').flushall()
     with self.assertNumQueries(6):
         self.client.get(reverse('user-list'))
Example #13
0
 def test_admin(self):
     """
     Tests that only the following db queries are done:
     * 7 requests to get the session an the request user with its permissions and
     * 1 requests to get the list of all files.
     """
     self.client.force_login(User.objects.get(pk=1))
     get_redis_connection('default').flushall()
     with self.assertNumQueries(8):
         self.client.get(reverse('mediafile-list'))
Example #14
0
 def test_anonymous(self):
     """
     Tests that only the following db queries are done:
     * 3 requests to get the permission for anonymous,
     * 1 requests to get the list of all topics,
     * 1 request to get attachments,
     * 1 request to get the agenda item,
     """
     get_redis_connection('default').flushall()
     with self.assertNumQueries(6):
         self.client.get(reverse('topic-list'))
Example #15
0
    def test_set_identifier_manually(self):
        """
        If the config is set to manually, the method does nothing.
        """
        config['motions_identifier'] = 'manually'
        get_redis_connection("default").flushall()
        motion = Motion()

        motion.set_identifier()

        # If the identifier should be set manually, the method does nothing
        self.assertIsNone(motion.identifier)
Example #16
0
    def test_clean_cache(self):
        """
        Tests that the data is retrieved from the database.
        """
        topic = Topic.objects.create(title='test topic')
        get_redis_connection("default").flushall()

        with self.assertNumQueries(3):
            collection_element = collection.CollectionElement.from_values('topics/topic', 1)
            instance = collection_element.get_full_data()

        self.assertEqual(topic.title, instance['title'])
Example #17
0
 def test_admin(self):
     """
     Tests that only the following db queries are done:
     * 7 requests to get the session an the request user with its permissions,
     * 1 requests to get the list of all topics,
     * 1 request to get attachments,
     * 1 request to get the agenda item
     """
     self.client.force_login(get_user_model().objects.get(pk=1))
     get_redis_connection('default').flushall()
     with self.assertNumQueries(10):
         self.client.get(reverse('topic-list'))
Example #18
0
    def test_admin(self):
        """
        Tests that only the following db queries are done:
        * 6 requests to get the session an the request user with its permissions and
        * 1 request to get the list of all groups.

        The data of the groups where loaded when the admin was authenticated. So
        only the list of all groups has be fetched from the db.
        """
        self.client.force_login(User.objects.get(pk=1))
        get_redis_connection('default').flushall()
        with self.assertNumQueries(7):
            self.client.get(reverse('group-list'))
Example #19
0
    def test_clean_cache(self):
        """
        Tests that the instances are retrieved from the database.
        """
        Topic.objects.create(title='test topic1')
        Topic.objects.create(title='test topic2')
        Topic.objects.create(title='test topic3')
        topic_collection = collection.Collection('topics/topic')
        get_redis_connection("default").flushall()

        with self.assertNumQueries(3):
            instance_list = list(topic_collection.get_full_data())
        self.assertEqual(len(instance_list), 3)
Example #20
0
    def test_with_cache(self):
        """
        Tests that no db query is used when the list is received twice.
        """
        get_redis_connection("default").flushall()
        Topic.objects.create(title='test topic1')
        Topic.objects.create(title='test topic2')
        Topic.objects.create(title='test topic3')
        topic_collection = collection.Collection('topics/topic')
        list(topic_collection.get_full_data())

        with self.assertNumQueries(0):
            instance_list = list(topic_collection.get_full_data())
        self.assertEqual(len(instance_list), 3)
Example #21
0
    def test_set_identifier_amendment(self):
        """
        If the motion is an amendment, the identifier is the identifier from the
        parent + a suffix.
        """
        config['motions_amendments_enabled'] = True
        self.motion.identifier = 'Parent identifier'
        self.motion.save()
        get_redis_connection("default").flushall()
        motion = Motion(parent=self.motion)

        motion.set_identifier()

        self.assertEqual(motion.identifier, 'Parent identifier - 1')
Example #22
0
    def test_set_identifier_second_amendment(self):
        """
        If a motion has already an amendment, the second motion gets another
        identifier.
        """
        config['motions_amendments_enabled'] = True
        self.motion.identifier = 'Parent identifier'
        self.motion.save()
        get_redis_connection("default").flushall()
        Motion.objects.create(title='Amendment1', parent=self.motion)
        motion = Motion(parent=self.motion)

        motion.set_identifier()

        self.assertEqual(motion.identifier, 'Parent identifier - 2')
Example #23
0
def view_page(request, char_id):
    con = get_redis_connection("persistent")

    page = cache.get("page:%s" % char_id)

    if page is None:
        try:
            page = Page.objects.get(char_id=char_id)
            cache.set("page:%s" % char_id, page, 600)
        except ObjectDoesNotExist:
            return render(request, "view_page/does_not_exist.html")
    elif not page:
        return render(request, "view_page/does_not_exist.html")

    page.dialoglog = json.loads(page.dialoglog)
    image_path = "../static/img/hs2/%s.gif" % page.image

    # Has the user voted
    ip = get_real_ip(request)
    voted = True if con.get("voted:%s:%s" % (ip, char_id)) else False

    return render(
        request, "view_page/view_page.html",
        {"page": page,
         "image_path": image_path,
         "voted": voted})
Example #24
0
    def refresh_access_token(self, channel_id):
        r = get_redis_connection()
        lock_name = self.TOKEN_REFRESH_LOCK % self.channel_uuid

        if not r.get(lock_name):
            with r.lock(lock_name, timeout=30):
                key = self.TOKEN_STORE_KEY % self.channel_uuid

                post_data = dict(grant_type="client_credentials", client_id=self.app_id, client_secret=self.app_secret)
                url = self.TOKEN_URL

                event = HttpEvent("POST", url, json.dumps(post_data))
                start = time.time()

                response = self._request(url, post_data, access_token=None)
                event.status_code = response.status_code

                if response.status_code != 200:
                    event.response_body = response.content
                    ChannelLog.log_channel_request(
                        channel_id, "Got non-200 response from %s" % self.API_NAME, event, start, True
                    )
                    return

                response_json = response.json()
                event.response_body = json.dumps(response_json)
                ChannelLog.log_channel_request(
                    channel_id, "Successfully fetched access token from %s" % self.API_NAME, event, start
                )

                access_token = response_json["access_token"]
                expires = response_json.get("expires_in", 7200)
                r.set(key, access_token, ex=int(expires))
                return access_token
Example #25
0
    def post(self, request):
        """保存用户浏览记录"""
        # 接收参数
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')

        # 校验参数:
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('sku不存在')

        # 保存用户浏览数据
        redis_conn = get_redis_connection('history')
        pl = redis_conn.pipeline()
        user_id = request.user.id

        # 先去重: 这里给 0 代表去除所有的 sku_id
        pl.lrem('history_%s' % user_id, 0, sku_id)
        # 再存储
        pl.lpush('history_%s' % user_id, sku_id)
        # 最后截取: 界面有限, 只保留 5 个
        pl.ltrim('history_%s' % user_id, 0, 4)
        # 执行管道
        pl.execute()

        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
Example #26
0
    def post(self, request):
        """"""
        # 获取参数
        sku_id = request.POST.get("sku_id")

        # 参数校验
        if not sku_id:
            return JsonResponse({"code": 1, "message": "参数缺失"})

        # 业务处理, 删除购物车数据
        if not request.user.is_authenticated():
            # 用户未登录,操作cookie
            cart_json = request.COOKIES.get("cart")
            if cart_json is not None:
                cart = json.loads(cart_json)
                # 判断cart字典中是否存在sku_id键
                if sku_id in cart:
                    # 删除cookie中cart字典的商品记录
                    del cart[sku_id]
                response = JsonResponse({"code": 0, "message": "删除成功"})
                response.set_cookie("cart", json.dumps(cart))
                return response
            else:
                return JsonResponse({"code": 0, "message": "删除成功"})
        else:
            # 用户已登录,操作redis
            redis_conn = get_redis_connection("default")
            user_id = request.user.id
            # 删除redis中的sku_id字段的记录
            redis_conn.hdel("cart_%s" % user_id, sku_id)
            return JsonResponse({"code": 0, "message": "删除成功"})
Example #27
0
def vote(request, char_id):
    """
    Vote a page up
    """
    con = get_redis_connection("persistent")

    page = cache.get("page:%s" % char_id)

    if page is None:
        try:
            page = Page.objects.get(char_id=char_id)
            cache.set("page:%s" % char_id, page)
        except ObjectDoesNotExist:
            return render(request, "view_page/does_not_exist.html")
    elif not page:
        return render(request, "view_page/does_not_exist.html")

    # Has the user already voted
    ip = get_real_ip(request)

    if con.get("voted:%s:%s" % (ip, char_id)):
        # Visitor has already voted, just redirect him/her
        return redirect("view_page", char_id=char_id)
    else:
        page.score += 1
        page.saved = True
        page.save()
        con.setex("voted:%s:%s" % (ip, char_id), 86400, True)
        cache.set("page:%s" % char_id, page, 600)

    return redirect("view_page", char_id=char_id)
Example #28
0
def maybe_start(run):
    """
    Either starts a new trial resume or returns nothing
    """
    if settings.FLOW_SERVER_TRIAL == "off":
        return None
    elif settings.FLOW_SERVER_TRIAL == "on":
        # very basic throttling
        r = get_redis_connection()
        if not r.set(TRIAL_LOCK, "x", TRIAL_PERIOD, nx=True):
            return None

        if not is_flow_suitable(run.flow):  # pragma: no cover
            r.delete(TRIAL_LOCK)
            return None

    elif settings.FLOW_SERVER_TRIAL == "always":
        pass

    try:
        is_simple = is_flow_simple(run.flow)

        logger.info(f"Starting flowserver trial resume for run {str(run.uuid)} in flow '{run.flow.name}'")
        return Trial(run, is_simple)

    except Exception as e:
        logger.error(f"Unable to reconstruct session for run {str(run.uuid)}: {str(e)}", exc_info=True)
        return None
Example #29
0
    def post(self, request, *args, **kwargs):
        if self.form.is_valid():
            user = self.form.cleaned_data['user']

            if settings.HAS_REDIS:
                from django_redis import get_redis_connection
                rc = get_redis_connection("redis")
                if rc.exists('pretix_pwreset_%s' % (user.id)):
                    user.log_action('pretix.control.auth.user.forgot_password.denied.repeated')
                    messages.error(request, _('We already sent you an email in the last 24 hours.'))
                    return redirect('control:auth.forgot')
                else:
                    rc.setex('pretix_pwreset_%s' % (user.id), 3600 * 24, '1')

            mail(
                user.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt',
                {
                    'user': user,
                    'url': (build_absolute_uri('control:auth.forgot.recover')
                            + '?id=%d&token=%s' % (user.id, default_token_generator.make_token(user)))
                },
                None, locale=user.locale
            )
            user.log_action('pretix.control.auth.user.forgot_password.mail_sent')
            messages.success(request, _('We sent you an e-mail containing further instructions.'))
            return redirect('control:auth.forgot')
        else:
            return self.get(request, *args, **kwargs)
Example #30
0
def get_sql_string_by_key(key):
    """Returns a SQL string from Redis using key
    :param key: A UUID pointing to the SQL string
    """
    # Since the records list endpoint bypasses the Django caching framework, do that here too
    redis_conn = get_redis_connection('default')
    return redis_conn.get(key)
Example #31
0
def get_assvideo_info(terminalE164):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_assvideo_info.lua')
    content = fileHandler.read()
    assvideo_info = conn.eval(content, 0, terminalE164)
    return json.loads(assvideo_info)
Example #32
0
def get_multi_meeting_detail(meetingE164,meetingType):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_muti_meeting_detail_info.lua')
    content = fileHandler.read()
    meeting_info = conn.eval(content, 0, meetingE164,meetingType)
    return json.loads(meeting_info)
Example #33
0
    def put(self, request):
        user = request.user

        # 1、提取参数
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected', True)

        # 2、校验参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'}, status=400)

        try:
            SKU.objects.get(pk=sku_id, is_launched=True)
        except SKU.DoesNotExist as e:
            print(e)
            return JsonResponse({'code': 404, 'errmsg': 'sku不存在'}, status=404)

        try:
            # count = int("5")
            count = int(count)
        except Exception as e:
            print(e)
            return JsonResponse({
                'code': 404,
                'errmsg': 'count参数有误'
            },
                                status=400)

        if not isinstance(selected, bool):
            return JsonResponse({
                'code': 404,
                'errmsg': 'selected参数有误'
            },
                                status=400)

        # 3、业务/数据处理 —— 修改redis or 修改cookie
        if user.is_authenticated:
            # 登陆状态,修改redis购物车数据
            conn = get_redis_connection('carts')
            # 商品数据:hash对象{16: 4}; 勾选状态:集合[16]
            conn.hset('carts_%d' % user.id, sku_id, count)
            if selected:
                conn.sadd('selected_%d' % user.id, sku_id)
            else:
                conn.srem('selected_%d' % user.id, sku_id)

            return JsonResponse({
                'code': 0,
                'errmsg': 'ok',
                'cart_sku': {
                    'sku_id': sku_id,
                    'count': count,
                    'selected': selected
                }
            })

        else:
            # 未登陆,修改cookie购物车数据
            # 购物车字典格式{1: {"count": 5, "selected": True}}
            cart_dict = None  # 改变是用来记录cookie中解码出来的购物车字典数据,如果cookie没有购物车该变量设置为空字典
            cookie_carts = request.COOKIES.get(
                'carts')  # "ASjibgrehgbBHBHlbgre=" or None
            if cookie_carts:
                cart_dict = CookieSecret.loads(
                    cookie_carts.encode())  # 解码得出字典数据
            else:
                cart_dict = {}

            # 修改购物车字典数据,重新写入cookie返回
            cart_dict[sku_id] = {'count': count, 'selected': selected}

            # 编码购物车数据设置到cookie中
            cookie_carts = CookieSecret.dumps(cart_dict)
            response = JsonResponse({
                'code': 0,
                'errmsg': 'ok',
                'cart_sku': {
                    'sku_id': sku_id,
                    'count': count,
                    'selected': selected
                }
            })
            response.set_cookie('carts', cookie_carts)
            return response
Example #34
0
def get_cascade_meeting(meetingE164,meetingName,start,count):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_cascade_meeting.lua')
    content = fileHandler.read()
    meeting_list = conn.eval(content, 0, meetingE164, meetingName,start,count)
    return json.loads(meeting_list)
Example #35
0
    def post(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', True)

        # 判断参数是否齐全
        if not all([sku_id, count]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断sku_id是否存在
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('商品不存在')
        # 判断count是否为数字
        try:
            count = int(count)
        except Exception:
            return http.HttpResponseForbidden('参数count有误')
        # 判断selected是否为bool值
        if selected:
            if not isinstance(selected, bool):
                return http.HttpResponseForbidden('参数selected有误')

        # 判断用户是否登录
        user = request.user
        if user.is_authenticated:
            # 用户已登录,操作redis购物车
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # 新增购物车数据
            pl.hincrby('carts_%s' % user.id, sku_id, count)
            # 新增选中的状态
            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)
            # 执行管道
            pl.execute()
            # 响应结果
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加购物车成功'})
        else:
            # 用户未登录,操作cookie购物车
            cart_str = request.COOKIES.get('carts')
            # 如果用户操作过cookie购物车
            if cart_str:
                # 将cart_str转成bytes,再将bytes转成base64的bytes,最后将bytes转字典
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:  # 用户从没有操作过cookie购物车
                cart_dict = {}

            # 判断要加入购物车的商品是否已经在购物车中,如有相同商品,累加求和,反之,直接赋值
            if sku_id in cart_dict:
                # 累加求和
                origin_count = cart_dict[sku_id]['count']
                count += origin_count
            cart_dict[sku_id] = {'count': count, 'selected': selected}
            # 将字典转成bytes,再将bytes转成base64的bytes,最后将bytes转字符串
            cookie_cart_str = base64.b64encode(
                pickle.dumps(cart_dict)).decode()

            # 创建响应对象
            response = http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': '添加购物车成功'
            })
            # 响应结果并将购物车数据写入到cookie
            response.set_cookie('carts',
                                cookie_cart_str,
                                max_age=constants.CARTS_COOKIE_EXPIRES)
            return response
Example #36
0
    def get(self, request, type_id, page_index):
        # 业务处理
        # 验证type_id是否存在
        try:
            goods_type = GoodsType.objects.get(id=type_id)
        except Exception as ex:
            return redirect(reverse('goods:index'))
        # 获取所有的类型
        types = GoodsType.objects.all()
        # 获取该种类的所有商品
        sort = request.GET.get('sort')
        # 按照一定规则进行排序
        if sort == 'price':
            skus = GoodsSKU.objects.filter(
                goods_type=goods_type).order_by('price')
        elif sort == 'hot':
            skus = GoodsSKU.objects.filter(
                goods_type=goods_type).order_by('-sales')
        else:
            sort = 'default'
            skus = GoodsSKU.objects.filter(
                goods_type=goods_type).order_by('id')
        # 分页显示
        paginator = Paginator(skus, 2)
        # 对页码进行容错处理
        page = paginator.get_page(page_index)
        # 自定义分页显示
        # 只显示五页,①当<5时,显示所有页面,②当大于5时,以其为中心,③末尾事显示后五页
        if paginator.num_pages < 5:
            page.index = range(1, paginator.num_pages + 1)
        elif paginator.num_pages >= page.number + 2 and page.number < 3:
            page.index = range(1, 6)
        elif paginator.num_pages >= page.number + 2 and page.number - 2 >= 1:
            page.index = range(page.number - 2, page.number + 3)
        else:
            page.index = range(paginator.num_pages - 4,
                               paginator.num_pages + 1)
        # 获取新品推荐
        new_goods = GoodsSKU.objects.filter(
            goods_type=goods_type).order_by('-create_time')[:2]
        # 获取用户购物车中的记录
        user = request.user
        cart_count = 0
        if user.is_authenticated:
            # 如果用户已登录
            # 得到Redis数据库的连接
            client = get_redis_connection('default')
            # 得到用户数据库的键
            cart_key = 'cart_%d' % user.id
            # 得到用户购物车的商品的数量
            cart_count = client.hlen(cart_key)
        # 组织模板上下文
        context = {
            'goods_type': goods_type,
            'types': types,
            'sort': sort,
            'page': page,
            'cart_count': cart_count,
            'new_goods': new_goods
        }

        return render(request, 'goods/list.html', context)
Example #37
0
    def post(self, request):
        # 有可能是登陆的User,有可能是未登陆的AnonymousUser
        user = request.user

        # 1、提取参数
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected', True)

        # 2、校验参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'}, status=400)

        try:
            SKU.objects.get(pk=sku_id, is_launched=True)
        except SKU.DoesNotExist as e:
            print(e)
            return JsonResponse({'code': 404, 'errmsg': 'sku不存在'}, status=404)

        try:
            # count = int("5")
            count = int(count)
        except Exception as e:
            print(e)
            return JsonResponse({
                'code': 404,
                'errmsg': 'count参数有误'
            },
                                status=400)

        if not isinstance(selected, bool):
            return JsonResponse({
                'code': 404,
                'errmsg': 'selected参数有误'
            },
                                status=400)

        # 3、数据/业务处理
        if user.is_authenticated:
            # 3.1、用户登陆,存redis
            conn = get_redis_connection('carts')
            # 3.1.1、redis添加sku商品和数量信息
            # hincrby carts_1 sku_id count --> sku_id不再哈希里面则新增,否则累加
            conn.hincrby('carts_%d' % user.id, sku_id, count)
            # 3.1.2、当前sku商品选中状态
            if selected:
                conn.sadd('selected_%d' % user.id, sku_id)
            else:
                conn.srem('selected_%d' % user.id, sku_id)

            return JsonResponse({'code': 0, 'errmsg': 'ok'})

        else:
            # 3.2、用户未登陆,存cookie
            # 约定:购物车字符串数据在cookie中存的时候是以"carts"作为key的
            # {"carts": "AnjBHJBnvjfkmrlngwjtNJKMLNJvgergr="}
            cookie_carts = request.COOKIES.get('carts')
            if cookie_carts:
                # 3.2.1、判断当前请求的cookie里面有没有购物车
                # 解码cookie购物数据
                cart_dict = CookieSecret.loads(cookie_carts.encode())
                # 3.2.1.1、判断当前新增的sku商品在不在原来的cookie购物车中,如果在则累加,不再则新建
                if sku_id in cart_dict:
                    # 累加
                    cart_dict[sku_id]['count'] += count
                    cart_dict[sku_id]['selected'] = selected
                else:
                    # 新增
                    cart_dict[sku_id] = {'count': count, 'selected': selected}
            else:
                # 3.2.2、如果购物车数据不存在
                cart_dict = {}
                cart_dict[sku_id] = {'count': count, 'selected': selected}

            # 编码购物车字典数据
            cookie_str = CookieSecret.dumps(cart_dict)
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', cookie_str)
            return response
Example #38
0
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.
from django.views.generic import View
from .models import *
from dtoken.views import make_token
from django_redis import get_redis_connection
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from .tasks import send_verify
from utils.loging_decorator import login_check
from utils.md5_pwd import hash_pwd
from django.views.decorators.csrf import csrf_exempt, csrf_protect
#用户模块异常码 10100-10199
# 处理和邮箱相关联的redis
email_redis = get_redis_connection('verify_email')


class BaseView(View):
    """
    作为基类,公共调用
    """
    def check_args(self, data, length):
        """
        用来检查用户传递的数据。是否为空。
        params : 前端传递的数据,格式为字典。
        return : 返回检查之后的数据
        """
        if len(data) != length:
            return JsonResponse({'code': 10101, 'error': 'Missing parameters'})
        for key, value in data.items():
Example #39
0
    def create(self, validated_data):
        """创建订单并保存订单数据"""
        # 获取address和pay_method
        address = validated_data['address']
        pay_method = validated_data['pay_method']

        # 获取登录用户
        user = self.context['request'].user

        # 订单编号:年月日时分秒+用户id
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + '%010d' % user.id

        # 商品总数量和实付款
        total_count = 0
        total_amount = Decimal(0)

        # 运费: 10
        freight = Decimal(10.0)

        # 订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:  # 货到付款
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']  # 待发货
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']  # 待支付

        # redis链接
        redis_conn = get_redis_connection('cart')

        # 从redis set中获取用户购物车中被勾选的商品sku_id(勾选就是要购买的)
        cart_selected_key = 'cart_selected_%s' % user.id

        # Set(b'<sku_id>', b'<sku_id>', ...)
        sku_ids = redis_conn.smembers(cart_selected_key)

        # 从redis hash中获取用户购物车中所有商品sku_id和对应的数量count
        cart_key = 'cart_%s' % user.id
        # {
        #     b'<sku_id>': b'<count>',
        #     ...
        # }
        cart_dict = redis_conn.hgetall(cart_key)

        with transaction.atomic():
            # with语句块中的代码,凡是涉及到数据库的操作,在进行数据库操作时会放在同一事务中

            # 设置一个事务的保存点
            sid = transaction.savepoint()

            try:
                # 1)向订单基本信息表添加一条记录
                order = OrderInfo.objects.create(order_id=order_id,
                                                 user=user,
                                                 address=address,
                                                 total_count=total_count,
                                                 total_amount=total_amount,
                                                 freight=freight,
                                                 pay_method=pay_method,
                                                 status=status)

                # 2)订单中包含几个商品,就向订单商品表中添加几条记录
                for sku_id in sku_ids:
                    # 获取购买的数量
                    count = cart_dict[sku_id]
                    count = int(count)

                    for i in range(3):
                        # 根据sku_id获取商品对象
                        # select * from tb_sku where id=<sku_id>;
                        sku = SKU.objects.get(id=sku_id)

                        # 判断库存
                        if count > sku.stock:
                            # 回滚事务到sid保存点,将sid保存点之后的sql语句的执行结果撤销
                            transaction.savepoint_rollback(sid)
                            raise serializers.ValidationError('商品库存不足')

                        # 记录查出的商品原始库存
                        origin_stock = sku.stock
                        new_stock = origin_stock - count
                        new_sales = sku.sales + count

                        # 模拟产生订单并发
                        # print('users: %s times: %s origin_stock: %s' % (user.id, i, origin_stock))
                        # import time
                        # time.sleep(10)

                        # 销量增加,库存减少
                        # update tb_sku
                        # set stock=<new_stock>, sales=<new_sales>
                        # where id=<sku_id>;
                        # sku.stock -= count
                        # sku.sales += count
                        # sku.save()

                        # update tb_sku
                        # set stock=<new_stock>, sales=<new_sales>
                        # where id=<sku_id> and stock=<origin_stock>;
                        # 返回是一个数字:代表被更新的行数
                        res = SKU.objects.filter(id=sku_id, stock=origin_stock).\
                            update(stock=new_stock, sales=new_sales)

                        if res == 0:
                            if i == 2:
                                # 连续更新了3次,仍然失败,直接下单失败
                                # 回滚事务到sid保存点,将sid保存点之后的sql语句的执行结果撤销
                                transaction.savepoint_rollback(sid)
                                raise serializers.ValidationError('下单失败2')
                            # 更新失败,商品的库存发生了变化,需要重新进行查询和更新
                            continue

                        # 向订单商品表中添加一条记录
                        OrderGoods.objects.create(order=order,
                                                  sku=sku,
                                                  count=count,
                                                  price=sku.price)

                        # 累加计算订单商品的总数量和总金额
                        total_count += count
                        total_amount += count * sku.price

                        # 跳出循环
                        break

                # 实付款
                total_amount += freight
                order.total_count = total_count
                order.total_amount = total_amount
                order.save()
            except serializers.ValidationError:
                # 继续向外抛出
                raise
            except Exception:
                # 下单失败,回滚事务到sid保存点,将sid保存点之后的sql语句的执行结果撤销
                transaction.savepoint_rollback(sid)
                raise serializers.ValidationError('下单失败1')

        # 3)清除购物车对应的购物车记录
        pl = redis_conn.pipeline()
        pl.hdel(cart_key, *sku_ids)
        pl.srem(cart_selected_key, *sku_ids)
        pl.execute()

        return order
Example #40
0
    def create_1(self, validated_data):
        """创建订单并保存订单数据"""
        # 获取address和pay_method
        address = validated_data['address']
        pay_method = validated_data['pay_method']

        # 获取登录用户
        user = self.context['request'].user

        # 订单编号:年月日时分秒+用户id
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + '%010d' % user.id

        # 商品总数量和实付款
        total_count = 0
        total_amount = Decimal(0)

        # 运费: 10
        freight = Decimal(10.0)

        # 订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:  # 货到付款
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']  # 待发货
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']  # 待支付

        # redis链接
        redis_conn = get_redis_connection('cart')

        # 从redis set中获取用户购物车中被勾选的商品sku_id(勾选就是要购买的)
        cart_selected_key = 'cart_selected_%s' % user.id

        # Set(b'<sku_id>', b'<sku_id>', ...)
        sku_ids = redis_conn.smembers(cart_selected_key)

        # 从redis hash中获取用户购物车中所有商品sku_id和对应的数量count
        cart_key = 'cart_%s' % user.id
        # {
        #     b'<sku_id>': b'<count>',
        #     ...
        # }
        cart_dict = redis_conn.hgetall(cart_key)

        with transaction.atomic():
            # with语句块中的代码,凡是涉及到数据库的操作,在进行数据库操作时会放在同一事务中

            # 设置一个事务的保存点
            sid = transaction.savepoint()

            try:
                # 1)向订单基本信息表添加一条记录
                order = OrderInfo.objects.create(order_id=order_id,
                                                 user=user,
                                                 address=address,
                                                 total_count=total_count,
                                                 total_amount=total_amount,
                                                 freight=freight,
                                                 pay_method=pay_method,
                                                 status=status)

                # 2)订单中包含几个商品,就向订单商品表中添加几条记录
                for sku_id in sku_ids:
                    # 获取购买的数量
                    count = cart_dict[sku_id]
                    count = int(count)

                    # 根据sku_id获取商品对象
                    # select * from tb_sku where id=<sku_id>;
                    # sku = SKU.objects.get(id=sku_id)

                    # select * from tb_sku where id=<sku_id> for update;
                    print('users: %s try get lock' % user.id)
                    sku = SKU.objects.select_for_update().get(
                        id=sku_id)  # 悲观锁(互斥锁)
                    print('users: %s get locked' % user.id)

                    # 判断库存
                    if count > sku.stock:
                        # 回滚事务到sid保存点,将sid保存点之后的sql语句的执行结果撤销
                        transaction.savepoint_rollback(sid)
                        raise serializers.ValidationError('商品库存不足')

                    # 模拟产生订单并发
                    # print('users: %s' % user.id)
                    import time
                    time.sleep(10)

                    # 销量增加,库存减少
                    sku.stock -= count
                    sku.sales += count
                    sku.save()

                    # 向订单商品表中添加一条记录
                    OrderGoods.objects.create(order=order,
                                              sku=sku,
                                              count=count,
                                              price=sku.price)

                    # 累加计算订单商品的总数量和总金额
                    total_count += count
                    total_amount += count * sku.price

                # 实付款
                total_amount += freight
                order.total_count = total_count
                order.total_amount = total_amount
                order.save()
            except serializers.ValidationError:
                # 继续向外抛出
                raise
            except Exception:
                # 下单失败,回滚事务到sid保存点,将sid保存点之后的sql语句的执行结果撤销
                transaction.savepoint_rollback(sid)
                raise serializers.ValidationError('下单失败1')

        # 3)清除购物车对应的购物车记录
        pl = redis_conn.pipeline()
        pl.hdel(cart_key, *sku_ids)
        pl.srem(cart_selected_key, *sku_ids)
        pl.execute()

        return order
Example #41
0
class OrdersViewSet(APIView):
    authentication_classes = [ApiAuth]
    conn = get_redis_connection("default")

    def post(self, request, *args, **kwargs):
        """
        立即支付
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        res = BaseResponse()

        try:

            web_price = float(request.data.get('price', ''))
            balance = float(request.data.get('balance', ''))
            user_id = request.auth.user_id

            # 校验数据合法性
            """
            2.1根据user_id获取用户数据库中的网站金币与前端1:1
            """
            user_balance = request.auth.user.balance
            print(user_balance)
            if balance > float(user_balance):
                res.code = 1040
                res.error = '账号余额不足'
                return Response(res.dict)
            settment_key = settings.PAYMENT_KEY % (user_id, '*')
            print(settment_key)
            all_key = self.conn.scan_iter(settment_key)
            course_all_price = 0
            # print(all_key)
            # 带限制的优惠券课程列表
            # [
            #     {
            #         'period_display': '24个月',
            #         'img': 'quanzhan.png',
            #         'policy_id': '2',
            #         'course_id': '1',
            #         'title': 'Python全栈',
            #         'default_coupon': '0',
            #         'coupon':
            #             {
            #                 '1':
            #                     {
            #                         'coupon_type': 1,
            #                         'coupon_display': '满减券',
            #                         'money_equivalent_value': 60,
            #                         'minimum_consume': 100},
            #                 '4':
            #                     {
            #                         'coupon_type': 1,
            #                         'coupon_display': '满减券',
            #                         'money_equivalent_value': 60,
            #                         'minimum_consume': 100
            #                     },
            #                 '5':
            #                     {
            #                         'coupon_type': 0,
            #                         'coupon_display': '通用券',
            #                         'money_equivalent_value': 40
            #                     }
            #             },
            #         'period': '720',
            #         'price': '3000.0'
            #
            #     },
            #     {
            #         'course_id': '2',
            #         'title': '金融分析',
            #         'img': 'jinrongfenxi.png',
            #         'policy_id': '4',
            #         'coupon': {},
            #         'default_coupon': '0',
            #         'period': '14',
            #         'period_display': '2周',
            #         'price': '12331.0'
            #
            #     }
            # ]
            course_list = []
            for key in all_key:
                print(key)
                info = {}
                data = self.conn.hgetall(key)
                print(data)
                for k, v in data.items():
                    kk = k.decode('utf-8')
                    if kk == "coupon":
                        info[kk] = json.loads(v.decode('utf-8'))
                    else:
                        info[kk] = v.decode('utf-8')
                course_list.append(info)
            print("course_list:", course_list)
            # 存放使用优惠券id列表
            use_coupon_record_id_list = []
            for i in course_list:
                course_id = i.get('course_id')
                # coupon_id = int(i.get('default_coupon'))
                coupon_id = 1
                course_obj = Course.objects.get(id=course_id)
                use_coupon_record_id_list.append(coupon_id)

                if course_obj.status == 1:
                    res.code = 1041
                    res.error = '课程已经下线'
                    return Response(res.dict)

                if coupon_id != 0:

                    coupon_dict = Coupon.objects.filter(
                        id=coupon_id,
                        couponrecord__account_id=user_id,
                        couponrecord__status=0,
                    ).values("coupon_type", "money_equivalent_value",
                             "minimum_consume", "off_percent")
                    print("coupon_dict:", coupon_dict)
                    if not coupon_dict:
                        res.code = 1042
                        res.error = '优惠券已过期'
                    coupon_dict = coupon_dict[0]

                    print("coupon_dict【0】:", coupon_dict)
                    price = float(i['price'])
                    # print("price:", price)
                    rebate_price = self.rebate(price, coupon_dict)

                    print("使用课程优惠券的rebate_price:", rebate_price)
                    i["rebate_price"] = rebate_price
                    # 此时的course_list结构
                    # {
                    #     'policy_id': '2',
                    #     'img': 'quanzhan.png',
                    #     'period_display': '24个月',
                    #     'coupon':
                    #         {
                    #             '1':
                    #                 {
                    #                     'coupon_type': 1,
                    #                     'coupon_display': '满减券',
                    #                     'money_equivalent_value': 60,
                    #                     'minimum_consume': 100
                    #
                    #                 },
                    #             '4':
                    #                 {
                    #                     'coupon_type': 1,
                    #                     'coupon_display': '满减券',
                    #                     'money_equivalent_value': 60,
                    #                     'minimum_consume': 100
                    #
                    #                 },
                    #             '5':
                    #                 {
                    #                     'coupon_type': 0,
                    #                     'coupon_display': '通用券',
                    #                     'money_equivalent_value': 40
                    #                 }
                    #         },
                    #     'default_coupon': '0',
                    #     'course_id': '1',
                    #     'title': 'Python全栈',
                    #     'period': '720',
                    #     'price': '3000.0',
                    #     'rebate_price': 2940.0
                    #
                    # }

                else:
                    coupon_dict = {}
                    rebate_price = float(i['price'])
                    print("无课程优惠券的rebate_price:", rebate_price)
                    pass
                if rebate_price == -1:
                    res.code = 1043
                    res.error = "优惠券不满足需求"
                    return Response(res.dict)
                # -- 8 得到所有课程折后价格的总和
                course_all_price += rebate_price
            # print("use_coupon_record_id_list:",use_coupon_record_id_list)
            # print("course_all_price:", course_all_price)
            # print("使用优惠券的course_list:",course_list)
            # 全局满减券
            global_coupon_dict = []

            global_coupon_key = settings.PAYMENT_COUPON_KEY % user_id
            # print("global_coupon_key:",global_coupon_key)
            # 2.全局优惠券
            global_coupon_dict = {
                'coupon':
                json.loads(
                    self.conn.hget(global_coupon_key,
                                   'coupon').decode('utf-8')),
                'default_coupon':
                self.conn.hget(global_coupon_key,
                               'default_coupon').decode('utf-8')
            }
            # print("全局优惠券:",global_coupon_dict)
            global_coupon_id = int(
                self.conn.hget(global_coupon_key,
                               'default_coupon').decode('utf-8'))

            print("全局优惠券id:", global_coupon_id)
            use_coupon_record_id_list.append(global_coupon_id)
            print("use_coupon_record_id_list", use_coupon_record_id_list)
            # global_coupon_id = 1
            if global_coupon_id != 0:

                # print("global_coupon_dict:", global_coupon_dict)
                # -- 去数据库校验
                global_coupon_dict = Coupon.objects.filter(
                    id=global_coupon_id,
                    couponrecord__account_id=user_id,
                    couponrecord__status=0,
                    valid_begin_date__lte=now(),
                    valid_end_date__gte=now()).values(
                        "coupon_type", "money_equivalent_value",
                        "minimum_consume", "off_percent")[0]
                print("global_coupon_dict[0]:", global_coupon_dict)
                # -- 全局优惠券合法 去做计算
                global_rebate_price = self.rebate(course_all_price,
                                                  global_coupon_dict)
                if global_rebate_price == -1:
                    res.code = 1044
                    res.error = "全局优惠券不满足需求"
                    return Response(res.dict)
                print("global_rebate_price:", global_rebate_price)

            else:
                global_coupon_dict = {}

                global_rebate_price = float(course_all_price)
                print("无全局优惠券价格:", global_rebate_price)

            # 抵扣账号余额 得到最终价格
            if global_rebate_price > balance:
                final_price = global_rebate_price - balance
                user_balance = user_balance - balance
            else:
                final_price = 0
                vir_price = global_rebate_price
                user_balance = user_balance - global_rebate_price
            print('final_price:', final_price)
            # 跟前端传过来的价格做校验
            if final_price != web_price:
                res.code = 1045
                res.error = "价格不合法"
                return Response(res.dict)
            # 创建订单 + 支付宝支付
            # 创建订单详细
            # 账号金额抵扣 + 账号金额记录
            # 优惠券状态更新
            # 当前时间

            current_date = datetime.datetime.now().date()
            current_datetime = datetime.datetime.now()
            actual_amount = 0
            if final_price != 0:
                payment_type = 1  # 支付宝
                actual_amount = final_price
            elif balance:
                payment_type = 3  # 账号余额支付
                actual_amount = global_rebate_price
            else:
                payment_type = 2  # 优惠码
                actual_amount = global_rebate_price
            # 购买课程列表course_list:
            #  course_list:
            # [
            # 	{
            # 		'course_id': '2',
            # 		'title': '金融分析',
            # 		'img': 'jinrongfenxi.png',
            # 		'policy_id': '4',
            # 		'coupon': {},
            # 		'default_coupon': '0',
            # 		'period': '14',
            # 		'period_display': '2周',
            # 		'price': '12331.0'
            #
            # 	},
            # 	{
            # 		'course_id': '1',
            # 		'title': 'Python全栈',
            # 		'period': '720',
            # 		'price': '3000.0'
            # 		'policy_id': '2',
            # 		'img': 'quanzhan.png',
            # 		'period_display': '24个月',
            # 		'default_coupon': '0',
            # 		'coupon':
            # 		{
            # 			'1':
            # 			{
            # 				'coupon_type': 1,
            # 				'coupon_display': '满减券',
            # 				'money_equivalent_value': 60,
            # 				'minimum_consume': 100
            #
            # 			},
            # 			'4':
            # 			{
            # 				'coupon_type': 1,
            # 				'coupon_display': '满减券',
            # 				'money_equivalent_value': 60,
            # 				'minimum_consume': 100
            #
            # 			},
            # 			'5':
            # 			{
            # 				'coupon_type': 0,
            # 				'coupon_display': '通用券',
            # 				'money_equivalent_value': 40
            # 			}
            # 		},
            #
            #
            #
            # 	}
            # ]
            print("payment_type", payment_type)
            with transaction.atomic():
                order_num = generate_order_num()
                print(order_num)
                if payment_type == 1:
                    order_object = models.Order.objects.create(
                        payment_type=payment_type,
                        order_number=order_num,
                        account=user_id,
                        actual_amount=actual_amount,
                        status=1,  # 待支付
                    )

                else:
                    order_object = models.Order.objects.create(
                        payment_type=payment_type,
                        order_number=order_num,
                        account=request.user,
                        actual_amount=actual_amount,
                        status=0,  # 支付成功,优惠券和贝里已够支付
                        pay_time=current_datetime)

                for item in course_list:
                    detail = models.OrderDetail.objects.create(
                        order=order_object,
                        content_object=models.Course.objects.get(
                            id=item['course_id']),
                        original_price=item['price'],
                        price=item['rebate_price'],
                        valid_period_display=item['period_display'],
                        valid_period=item['period'])
                user_balance = models.Account.objects.filter(
                    id=user_id).update(balance=user_balance)
                models.TransactionRecord.objects.create(
                    account=user_id,
                    amount=actual_amount,
                    transaction_type=1,
                    content_object=order_object,
                    transaction_number=generate_transaction_num())
                effect_row = models.CouponRecord.objects.filter(
                    id__in=use_coupon_record_id_list).update(
                        order=order_object, used_time=current_datetime)
                if effect_row != len(use_coupon_record_id_list):
                    raise Exception('优惠券使用失败')

                res.data = {'payment_type': payment_type}
                # 生成支付宝URL地址
                if payment_type == 1:
                    pay = AliPay()
                    query_params = pay.direct_pay(
                        subject="Twiss",  # 商品简单描述
                        out_trade_no=order_num,  # 商户订单号
                        total_amount=actual_amount,  # 交易金额(单位: 元 保留俩位小数)
                    )
                    pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(
                        query_params)

                    res.data = {'pay_url': pay_url}

        except Exception as e:
            res.code = 1002
            res.error = "支付失败"
        return Response(res.dict)

    def rebate(self, price, coupon_dict):
        coupon_type = coupon_dict.get('coupon_type', '')
        if coupon_type == 0:  # 通用优惠券
            rebate_price = price - int(coupon_dict['money_equivalent_value'])
            if rebate_price < 0:
                rebate_price = 0
        elif coupon_type == 1:
            # 满减型优惠券
            rebate_price = price - int(coupon_dict['money_equivalent_value'])
            # if price<coupon_dict['minimum_consume']:
            #     rebate_price=-1
        else:  # 折扣型
            rebate_price = price * int(coupon_dict['off_percent']) / 100
            if price < coupon_dict['minimum_consume']:
                rebate_price = -1
        return rebate_price
Example #42
0
    def post(self,request):

        # 接收参数
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        # 校验参数
        if not all([address_id, pay_method]):
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            address = Address.objects.get(id=address_id)
        except:
            return http.HttpResponseForbidden('参数pay_method错误')
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'],OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden('参数pay_method错误')




        from django.db import transaction

        # -----------设置事务起点----------
        with transaction.atomic():

            # ----------设置事务保存点---------
            save_id = transaction.savepoint()

            try:

                # 获取用户对象
                user = request.user
                # 生成订单号
                order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)

                # 保存订单基本信息
                order = OrderInfo.objects.create(

                order_id = order_id,
                user = user,
                address = address,
                total_count = 0,
                total_amount = Decimal('0'),
                freight = Decimal('10.00'),
                pay_method = pay_method,
                status = OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY']
                else OrderInfo.ORDER_STATUS_ENUM['UNSEND']

            )

                # 查询用户选中的购物车数据
                redis_conn = get_redis_connection('carts')
                redis_data = redis_conn.hgetall(user.id)

                carts_dict = {}
                # 取出用户选中的购物车数据
                for key,value in redis_data.items():
                    sku_id = int(key.decode())
                    sku_value = json.loads(value.decode())
                    # 判断是否选中
                    if sku_value['selected']:
                        carts_dict[sku_id] = sku_value

                # 根据选中的购物车数据 遍历商品信息
                for sku_id in carts_dict.keys():

                    while True:

                        sku = SKU.objects.get(id=sku_id)

                        # 设置当前商品操作前(原始)的库存量和销量
                        old_stock = sku.stock
                        old_sales = sku.sales

                        # 取出购物车数据中当前商品的数量(也就是用户购买的当前商品的数量)
                        sku_count = carts_dict[sku_id]['count']
                        # 判断库存是否充足
                        if sku_count > sku.stock:

                            # ------------事务回滚--------------
                            transaction.savepoint_rollback(save_id)

                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})



                        # # 动态修改sku表中的数据 库存减少,销量增加
                        # sku.sales += sku_count
                        # sku.stock -= sku_count
                        # sku.save()

                        # # 模拟资源竞争
                        # import time
                        # time.sleep(10)

                        # 使用乐观锁 更新库存量和销量
                        new_stock = old_stock - sku_count
                        new_sales = old_sales + sku_count
                        result = SKU.objects.filter(id=sku_id,stock = old_stock).update(stock=new_stock,sales=new_sales)


                        # 如果下单失败 --库存足够就继续下单 直到下单成功或库存不足
                        if result == 0:
                            continue

                        # 动态修改spu表中的数据 分类销量增加
                        sku.spu.sales += sku_count
                        sku.spu.save()

                        # 动态修改商品基本信息表中的 总数量和 总价
                        order.total_count += sku_count
                        order.total_amount += sku_count * sku.price

                        # 保存商品信息数据
                        OrderGoods.objects.create(
                            order = order,
                            sku = sku,
                            count = sku_count,
                            price = sku.price,
                        )

                        # 下单成功 或 失败跳出
                        break

                # 商品总价钱加上 运费
                order.total_amount += order.freight
                # 保存订单
                order.save()

            except:
                # ------------事务回滚------------
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单失败'})


            # ---------------提交事务-------------
            transaction.savepoint_commit(save_id)


        # 清除购物车中已经结算过的商品
        redis_conn.hdel(user.id,*carts_dict)

        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})
Example #43
0
def get_meeting_terminal_detail(terminalE164):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_meeting_terminal_detail.lua')
    content = fileHandler.read()
    terminal_info = conn.eval(content, 0, terminalE164)
    return json.loads(terminal_info)
Example #44
0
    def post(self, request):
        """
        保存购物车

        登录用户购物车数据,保存在Redis中:
                carts_user_id: {sku_id1: count, sku_id3: count, sku_id5: count, ...}
                selected_user_id: [sku_id1, sku_id3, ...]

        未登录用户购物车数据,以字符串保存在cookie中:
                {
                    "sku_id1":{
                        "count":"1",
                        "selected":"True"
                    },
                    "sku_id3":{
                        "count":"3",
                        "selected":"True"
                    },
                    "sku_id5":{
                        "count":"3",
                        "selected":"False"
                    }
                }
        """
        # 接收、校验参数
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected', True)  # 可选,默认购物车中商品都会被勾选
        # 判断参数是否齐全
        if not all([sku_id, count]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断sku_id是否合法
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('参数sku_id错误')
        # 判断count是否为整数
        if not isinstance(count, int):
            return http.HttpResponseForbidden('参数count错误')
        # 判断selected是否为bool类型
        if selected is not True:
            if not isinstance(selected, bool):
                return http.HttpResponseForbidden('参数selected错误')
        # 判断用户是否登录
        user = request.user
        if user.is_authenticated:
            # 如果用户已登录,操作Redis购物车
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # 需要以增量计算的形式保存商品数据
            pl.hincrby('carts_{}'.format(user.id), sku_id, count)
            # 保存商品勾选状态
            if selected is True:
                pl.sadd('selected_{}'.format(user.id), sku_id)
            try:
                # 执行管道
                pl.execute()
            except Exception as e:
                logger.error(e)
                return http.JsonResponse({
                    'code': RETCODE.DBERR,
                    'errmsg': err_msg[RETCODE.DBERR]
                })
            # 响应结果
            return http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': err_msg[RETCODE.OK]
            })
        else:
            # 如果用户未登录,操作cookie购物车
            # 获取cookies中的购物车数据,判断是否有购物车数据
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                # 如果有,提取原来的购物车数据
                cart_str_bytes = cart_str.encode()
                cart_dict_bytes = base64.b64decode(cart_str_bytes)
                cart_dict = pickle.loads(cart_dict_bytes)
                # 判断当前要添加的商品是否在购物车cart_dict中
                if sku_id in cart_dict:
                    # 如果有,更新当前商品的数量,做增量计算
                    origin_count = cart_dict.get(sku_id).get('count')
                    count += origin_count
            else:
                # 如果没有,创建新的购物车数据
                cart_dict = {}
            # 更新购物车数据
            cart_dict[sku_id] = {'count': count, 'selected': selected}
            # 购物车数据加密序列化
            cart_dict_bytes = pickle.dumps(cart_dict)
            cart_bytes_str = base64.b64encode(cart_dict_bytes)
            cart_str = cart_bytes_str.decode()
            # 将新的购物车数据写入到cookies中
            response = http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': err_msg[RETCODE.OK]
            })
            response.set_cookie('carts',
                                cart_str,
                                max_age=constants.ANONYMOUS_USER_CART_EXPIRES)
        # 响应结果
        return response
Example #45
0
    def post(self, request):
        """处理登陆逻辑"""
        #     接受登陆请求参数
        user_name = request.POST.get('user_name')
        pwd = request.POST.get('pwd')
        #       校验登陆请求参数
        if not all([user_name, pwd]):
            # 判断是否有
            return redirect(reverse('users:login'))


#         判断是否存在  authenticate属性就是判断是否存在
        user = authenticate(username=user_name, password=pwd)
        print(user)
        if user is None:
            # 提示用户:用户名或者密码错误
            return render(request, 'login.html', {'errmsg': '用户名或者密码错误'})

        # 判断用户是否是激活用户
        if user.is_active == False:
            # 提示用户激活
            return render(request, 'login.html', {'errmsg': '请激活'})

        # 登陆用户 主要是生成状态保持数据,并默认写入到django——session表中
        # 如果调用login方法 没有指定SESSION_ENGINE,那么就默认存到django—session中
        # 指定了之后,就按照引擎的指引进行session数据的存储,需要搭配djan——redis使用
        login(request, user)

        #         记住用户名  多少天免登陆   如果用户勾选了‘记住用户名’,就把状态保持,反之保持0秒
        remembered = request.POST.get('remembered')
        if remembered != 'on':
            request.session.set_expiry(0)  #没有勾选  保持0秒
        else:
            request.session.set_expiry(60 * 60 * 24 * 10)  #保持10天

        # 在界面跳转以前,将cookie中的购物车合并到redis中
        cart_json = request.COOKIES.get('cart')
        if cart_json is not None:
            # cookie中得捣的key是str,val是int
            cart_dict_cookie = json.loads(cart_json)
        else:
            cart_dict_cookie = {}

        # 查询redis中的购物车信息
        redis_coon = get_redis_connection('default')
        # 通过django——redis得捣的key和val都是bytes类型的
        cart_dict_redis = redis_coon.hgetall('cart_%s' % user.id)

        # 遍历cart_dict_cookie,取出sku_id,count信息
        for sku_id, count in cart_dict_cookie.items():
            sku_id = sku_id.encode()  # 将 str转化成bytes类型
            if sku_id in cart_dict_redis:
                origin_count = cart_dict_redis[sku_id]
                count += int(origin_count)

                # # 在这里合并可能造成库存不足
                # sku = GoodsSKU.objects.get(id=sku_id)
                # if count > sku.stock:
                #     pass   #这个只可能是在这里出现,一般情况只有在登陆的时候才会查询购物车信息,所以这里不做解释

            # 保存合并的数据到redis
            cart_dict_redis[sku_id] = count
        # 一次性向redis中添加数据
        if cart_dict_redis:
            redis_coon.hmset('cart_%s' % user.id, cart_dict_redis)

        # 在界面跳转以前,判断,有next就跳转next,没有就转到主页
        next = request.GET.get('next')
        if next is None:
            # 响应结果
            response = redirect(reverse('goods:index'))  #跳转到主页
        else:
            # 这里添加一个跳转的问题,这里只接受post
            if next == '/orders/place':
                response = redirect(reverse('cart:info'))
            else:
                response = redirect('/orders/place')

        # 删除cookie中的数据
        response.delete_cookie('cart')

        return response
Example #46
0
    def post(request):
        """
        提交表单时的逻辑
        :param request:
        :return: redirect(index.html) or render(register.html)
        """
        # 注册时的表单数据接受和判定
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        # 电话号码
        mobile = request.POST.get('mobile')
        # 短信验证吗
        sms_code = request.POST.get('sms_code')
        # 协议是否勾选
        allow = request.POST.get('allow')

        # 前段已经对注册的数据进行过校验--是否符合规则,如果后台校验失败,代表是非正常途径传过来的数据,直接禁止掉
        if not all([username, password, password2, mobile, sms_code, allow]):
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输入5-20个字符的用户名')
        if not re.match(r'^[0-9a-zA-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20位的密码')
        if password != password2:
            return http.HttpResponseForbidden('请输入8-20位的密码')

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')
        # 协议选中 前端会给个值 on
        if allow != 'on':
            return http.HttpResponseForbidden('请勾选用户协议')

        # 提交数据后对段兴验证码进行判断 --- 不需要对 图形验证码进行判断,只有图形验证码输入这个你却才可以发短信
        sms_client = get_redis_connection('sms_code')
        ret_code = sms_client.get('%s' % mobile)
        if ret_code is None:
            return render(request, 'register.html',
                          {'sms_code_errmsg': '无效的短信验证码'})
        if ret_code.decode() != sms_code:
            # 用 render 会直接刷新页面导致前面的数据无法再用,导致浪费,而且用户体验不好
            # 当输入错误时,应该只显示错误信息,不刷新页面
            return render(request, 'register.html',
                          {'sms_code_errmsg': '短信验证码输入错误'})
        # 验证成功删除当前redis中的对应数据 --- 可能导致错误
        sms_client.delete('%s' % mobile)

        # 为了测试方便,先不存入数据库
        try:
            user = User.objects.create_user(username=username,
                                            password=password,
                                            mobile=mobile)
        except DatabaseError:
            # logger.error(e)
            return render(request, 'register.html',
                          {'register_errmsg': '注册失败'})
        # django内部封装的login(),可以保持会话状态
        login(request, user)

        #  namespace:name   主路由:子路由 注册成功,直接跳转到主页index
        response = redirect(reverse('contents:index'))
        response.set_cookie('username', username, max_age=3600 * 24 * 15)
        return response
Example #47
0
    def get(self, request, sku_id):
        # 尝试获取缓存数据
        context = cache.get("detail_%s" % sku_id)
        # 如果缓存不存在
        if context is None:
            try:
                # 获取商品信息
                sku = GoodsSKU.objects.get(id=sku_id)
            except GoodsSKU.DoesNotExist:
                # from django.http import Http404
                # raise Http404("商品不存在!")
                return redirect(reverse("goods:index"))

            # 获取类别
            categorys = GoodsCategory.objects.all()

            # 从订单中获取评论信息
            sku_orders = sku.ordergoods_set.all().order_by('-create_time')[:30]
            if sku_orders:
                for sku_order in sku_orders:
                    sku_order.ctime = sku_order.create_time.strftime(
                        '%Y-%m-%d %H:%M:%S')
                    sku_order.username = sku_order.order.user.username
            else:
                sku_orders = []

            # 获取最新推荐
            new_skus = GoodsSKU.objects.filter(
                category=sku.category).order_by("-create_time")[:2]

            # 获取其他规格的商品
            goods_skus = sku.goods.goodssku_set.exclude(id=sku_id)

            context = {
                "categorys": categorys,
                "sku": sku,
                "orders": sku_orders,
                "new_skus": new_skus,
                "goods_skus": goods_skus
            }

            # 设置缓存
            cache.set("detail_%s" % sku_id, context, 3600)

        # 购物车数量
        cart_num = self.get_cart_num(request)

        # 浏览记录
        # 如果是登录的用户
        if request.user.is_authenticated():
            redis_conn = get_redis_connection("default")
            user_id = request.user.id
            # 移除已经存在的本商品浏览记录
            redis_conn.lrem("history_%s" % user_id, 0, sku_id)
            # 添加新的浏览记录
            redis_conn.lpush("history_%s" % user_id, sku_id)
            # 只保存最多5条记录
            redis_conn.ltrim("history_%s" % user_id, 0, 4)

        context.update({"cart_num": cart_num})

        return render(request, 'detail.html', context)
Example #48
0
 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', True)
     # 判断参数是否齐全
     if not all([sku_id, count]):
         return http.HttpResponseForbidden('缺少必传参数')
     # 判断sku_id是否存在
     try:
         sku = SKU.objects.get(id=sku_id)
     except SKU.DoesNotExist:
         return http.HttpResponseForbidden('商品sku_id不存在')
     # 判断count是否为整数
     if not isinstance(count, int):
         return http.HttpResponseForbidden('参数count错误')
     # 判断selected是否为bool类型
     if selected is not True:
         if not isinstance(selected, bool):
             return http.HttpResponseForbidden('参数selected错误')
     # 创建数据对象
     cart_sku = {
         'id': sku_id,
         'count': count,
         'selected': selected,
         'name': sku.name,
         'default_image_url': sku.default_image.url,
         'price': sku.price,
         'amount': sku.price * count,
     }
     # 判断用户是否登录
     user = request.user
     if user.is_authenticated:
         # 用户已登录,修改redis购物车
         redis_conn = get_redis_connection('carts')
         pl = redis_conn.pipeline()
         # 由于后端收到的商品数量是最终结果,因此直接覆盖写入
         pl.hset('carts_%s' % user.id, sku_id, count)
         # 修改勾选状态
         if selected:
             pl.sadd('selected_%s' % user.id, sku_id)
         else:
             pl.srem('selected_%s' % user.id, sku_id)
         # 执行
         pl.execute()
         return http.JsonResponse({
             'code': RETCODE.OK,
             'errmsg': err_msg[RETCODE.OK],
             'cart_sku': cart_sku
         })
     else:
         # 用户未登录,修改cookies中的购物车数据
         cart_str = request.COOKIES.get('carts')
         # 判断是否有购物车数据
         if cart_str:
             # 如果有,提取原来的购物车数据
             cart_str_bytes = cart_str.encode()
             cart_dict_bytes = base64.b64decode(cart_str_bytes)
             cart_dict = pickle.loads(cart_dict_bytes)
         else:
             # 如果没有,创建新的购物车数据
             cart_dict = {}
         # 修改购物车数据,后端收到的是最终的商品数量,覆盖写入
         cart_dict[sku_id] = {'count': count, 'selected': selected}
         # 购物车数据加密序列化
         cart_dict_bytes = pickle.dumps(cart_dict)
         cart_bytes_str = base64.b64encode(cart_dict_bytes)
         cart_str = cart_bytes_str.decode()
         # 响应结果
         response = http.JsonResponse({
             'code': RETCODE.OK,
             'errmsg': err_msg[RETCODE.OK],
             'cart_sku': cart_sku
         })
         response.set_cookie('carts',
                             cart_str,
                             max_age=constants.ANONYMOUS_USER_CART_EXPIRES)
         return response
Example #49
0
    def pull_results(self,
                     poll,
                     modified_after,
                     modified_before,
                     progress_callback=None):
        org = poll.org
        r = get_redis_connection()
        key = Poll.POLL_PULL_RESULTS_TASK_LOCK % (org.pk, poll.flow_uuid)

        stats_dict = dict(
            num_val_created=0,
            num_val_updated=0,
            num_val_ignored=0,
            num_path_created=0,
            num_path_updated=0,
            num_path_ignored=0,
            num_synced=0,
        )

        if poll.stopped_syncing:
            return (
                stats_dict["num_val_created"],
                stats_dict["num_val_updated"],
                stats_dict["num_val_ignored"],
                stats_dict["num_path_created"],
                stats_dict["num_path_updated"],
                stats_dict["num_path_ignored"],
            )

        if r.get(key):
            logger.info(
                "Skipping pulling results for poll #%d on org #%d as it is still running"
                % (poll.pk, org.pk))
        else:
            with r.lock(key, timeout=Poll.POLL_SYNC_LOCK_TIMEOUT):
                lock_expiration = time.time(
                ) + 0.8 * Poll.POLL_SYNC_LOCK_TIMEOUT
                client = self._get_client(org, 2)

                questions_uuids = poll.get_question_uuids()

                # ignore the TaskState time and use the time we stored in redis
                (
                    after,
                    before,
                    latest_synced_obj_time,
                    batches_latest,
                    resume_cursor,
                    pull_after_delete,
                ) = poll.get_pull_cached_params()

                if pull_after_delete is not None:
                    after = None
                    latest_synced_obj_time = None
                    batches_latest = None
                    resume_cursor = None
                    poll.delete_poll_results()
                    pull_refresh_from_archives.apply_async((poll.pk, ),
                                                           queue="sync")

                if resume_cursor is None:
                    before = datetime_to_json_date(timezone.now())
                    after = latest_synced_obj_time

                start = time.time()
                logger.info("Start fetching runs for poll #%d on org #%d" %
                            (poll.pk, org.pk))

                poll_runs_query = client.get_runs(flow=poll.flow_uuid,
                                                  after=after,
                                                  before=before)
                fetches = poll_runs_query.iterfetches(
                    retry_on_rate_exceed=True, resume_cursor=resume_cursor)

                try:
                    fetch_start = time.time()
                    for fetch in fetches:

                        logger.info("RapidPro API fetch for poll #%d "
                                    "on org #%d %d - %d took %ds" % (
                                        poll.pk,
                                        org.pk,
                                        stats_dict["num_synced"],
                                        stats_dict["num_synced"] + len(fetch),
                                        time.time() - fetch_start,
                                    ))

                        contacts_map, poll_results_map, poll_results_to_save_map = self._initiate_lookup_maps(
                            fetch, org, poll)

                        for temba_run in fetch:

                            if batches_latest is None or temba_run.modified_on > json_date_to_datetime(
                                    batches_latest):
                                batches_latest = datetime_to_json_date(
                                    temba_run.modified_on.replace(
                                        tzinfo=pytz.utc))

                            contact_obj = contacts_map.get(
                                temba_run.contact.uuid, None)
                            self._process_run_poll_results(
                                org,
                                questions_uuids,
                                temba_run,
                                contact_obj,
                                poll_results_map,
                                poll_results_to_save_map,
                                stats_dict,
                            )

                        stats_dict["num_synced"] += len(fetch)
                        if progress_callback:
                            progress_callback(stats_dict["num_synced"])

                        self._save_new_poll_results_to_database(
                            poll_results_to_save_map)

                        logger.info(
                            "Processed fetch of %d - %d "
                            "runs for poll #%d on org #%d" %
                            (stats_dict["num_synced"] - len(fetch),
                             stats_dict["num_synced"], poll.pk, org.pk))
                        fetch_start = time.time()
                        logger.info("=" * 40)

                        if (stats_dict["num_synced"] >=
                                Poll.POLL_RESULTS_MAX_SYNC_RUNS
                                or time.time() > lock_expiration):
                            poll.rebuild_poll_results_counts()

                            cursor = fetches.get_cursor()
                            self._mark_poll_results_sync_paused(
                                org, poll, cursor, after, before,
                                batches_latest)

                            logger.info(
                                "Break pull results for poll #%d on org #%d in %ds, "
                                " Times: after= %s, before= %s, batch_latest= %s, sync_latest= %s"
                                " Objects: created %d, updated %d, ignored %d. "
                                "Before cursor %s" % (
                                    poll.pk,
                                    org.pk,
                                    time.time() - start,
                                    after,
                                    before,
                                    batches_latest,
                                    latest_synced_obj_time,
                                    stats_dict["num_val_created"],
                                    stats_dict["num_val_updated"],
                                    stats_dict["num_val_ignored"],
                                    cursor,
                                ))

                            return (
                                stats_dict["num_val_created"],
                                stats_dict["num_val_updated"],
                                stats_dict["num_val_ignored"],
                                stats_dict["num_path_created"],
                                stats_dict["num_path_updated"],
                                stats_dict["num_path_ignored"],
                            )
                except TembaRateExceededError:
                    poll.rebuild_poll_results_counts()

                    cursor = fetches.get_cursor()
                    self._mark_poll_results_sync_paused(
                        org, poll, cursor, after, before, batches_latest)

                    logger.info(
                        "Break pull results for poll #%d on org #%d in %ds, "
                        " Times: after= %s, before= %s, batch_latest= %s, sync_latest= %s"
                        " Objects: created %d, updated %d, ignored %d. "
                        "Before cursor %s" % (
                            poll.pk,
                            org.pk,
                            time.time() - start,
                            after,
                            before,
                            batches_latest,
                            latest_synced_obj_time,
                            stats_dict["num_val_created"],
                            stats_dict["num_val_updated"],
                            stats_dict["num_val_ignored"],
                            cursor,
                        ))

                    return (
                        stats_dict["num_val_created"],
                        stats_dict["num_val_updated"],
                        stats_dict["num_val_ignored"],
                        stats_dict["num_path_created"],
                        stats_dict["num_path_updated"],
                        stats_dict["num_path_ignored"],
                    )

                if batches_latest is not None and (
                        latest_synced_obj_time is None
                        or json_date_to_datetime(latest_synced_obj_time) <=
                        json_date_to_datetime(batches_latest)):
                    latest_synced_obj_time = batches_latest

                self._mark_poll_results_sync_completed(poll, org,
                                                       latest_synced_obj_time)

                # from django.db import connection as db_connection, reset_queries
                # slowest_queries = sorted(db_connection.queries, key=lambda q: q['time'], reverse=True)[:10]
                # for q in slowest_queries:
                #     print "=" * 60
                #     print "\n\n\n"
                #     print "%s -- %s" % (q['time'], q['sql'])
                # reset_queries()

                logger.info(
                    "Finished pulling results for poll #%d on org #%d runs in %ds, "
                    "Times: sync_latest= %s,"
                    "Objects: created %d, updated %d, ignored %d" % (
                        poll.pk,
                        org.pk,
                        time.time() - start,
                        latest_synced_obj_time,
                        stats_dict["num_val_created"],
                        stats_dict["num_val_updated"],
                        stats_dict["num_val_ignored"],
                    ))
        return (
            stats_dict["num_val_created"],
            stats_dict["num_val_updated"],
            stats_dict["num_val_ignored"],
            stats_dict["num_path_created"],
            stats_dict["num_path_updated"],
            stats_dict["num_path_ignored"],
        )
Example #50
0
    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', True)

        # 判断参数是否齐全
        if not all([sku_id, count]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断sku_id是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('商品sku_id不存在')
        # 判断count是否为数字
        try:
            count = int(count)
        except Exception:
            return http.HttpResponseForbidden('参数count有误')
        # 判断selected是否为bool值
        if selected:
            if not isinstance(selected, bool):
                return http.HttpResponseForbidden('参数selected有误')

        # 判断用户是否登录
        user = request.user
        if user.is_authenticated:
            # 用户已登录,修改redis购物车
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # 因为接口设计为幂等的,直接覆盖
            pl.hset('carts_%s' % user.id, sku_id, count)
            # 是否选中
            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)
            else:
                pl.srem('selected_%s' % user.id, sku_id)
            pl.execute()

            # 创建响应对象
            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'amount': sku.price * count,
            }
            return http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': '修改购物车成功',
                'cart_sku': cart_sku
            })
        else:
            # 用户未登录,修改cookie购物车
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                # 将cart_str转成bytes,再将bytes转成base64的bytes,最后将bytes转字典
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart_dict = {}
            # 因为接口设计为幂等的,直接覆盖
            cart_dict[sku_id] = {'count': count, 'selected': selected}
            # 将字典转成bytes,再将bytes转成base64的bytes,最后将bytes转字符串
            cookie_cart_str = base64.b64encode(
                pickle.dumps(cart_dict)).decode()

            # 创建响应对象
            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'amount': sku.price * count,
            }
            response = http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': '修改购物车成功',
                'cart_sku': cart_sku
            })
            # 响应结果并将购物车数据写入到cookie
            response.set_cookie('carts',
                                cookie_cart_str,
                                max_age=constants.CARTS_COOKIE_EXPIRES)
            return response
Example #51
0
    def pull_results_from_archives(self, poll):
        org = poll.org
        r = get_redis_connection()
        key = Poll.POLL_PULL_RESULTS_TASK_LOCK % (org.pk, poll.flow_uuid)

        stats_dict = dict(
            num_val_created=0,
            num_val_updated=0,
            num_val_ignored=0,
            num_path_created=0,
            num_path_updated=0,
            num_path_ignored=0,
            num_synced=0,
        )

        if poll.stopped_syncing:
            return (
                stats_dict["num_val_created"],
                stats_dict["num_val_updated"],
                stats_dict["num_val_ignored"],
                stats_dict["num_path_created"],
                stats_dict["num_path_updated"],
                stats_dict["num_path_ignored"],
            )

        with r.lock(key):
            first = poll.poll_date.replace(day=1,
                                           hour=0,
                                           minute=0,
                                           second=0,
                                           microsecond=0)

            client = self._get_client(org, 2)

            questions_uuids = poll.get_question_uuids()
            archives_query = client.get_archives(archive_type="run",
                                                 after=first)
            archives_fetches = archives_query.iterfetches(
                retry_on_rate_exceed=True)

            i = 0
            for archives in archives_fetches:

                for archive in archives:
                    i += 1
                    logger.info("Archive %d with %d records, size %d" %
                                (i, archive.record_count, archive.size))

                    try:
                        start_archive = time.time()
                        logger.info("Archive %d has %d records" %
                                    (i, archive.record_count))

                        if archive.record_count <= 0:
                            continue

                        flow_uuid = poll.flow_uuid

                        for fetch in self._iter_poll_record_runs(
                                archive, flow_uuid):

                            fetch_start = time.time()

                            contacts_map, poll_results_map, poll_results_to_save_map = self._initiate_lookup_maps(
                                fetch, org, poll)

                            for temba_run in fetch:

                                contact_obj = contacts_map.get(
                                    temba_run.contact.uuid, None)
                                self._process_run_poll_results(
                                    org,
                                    questions_uuids,
                                    temba_run,
                                    contact_obj,
                                    poll_results_map,
                                    poll_results_to_save_map,
                                    stats_dict,
                                )

                            stats_dict["num_synced"] += len(fetch)

                            self._save_new_poll_results_to_database(
                                poll_results_to_save_map)

                            logger.info(
                                "Processing archive %d took %ds for fetch of %d"
                                % (i, time.time() - fetch_start, len(fetch)))

                        logger.info("Full poll process archive in %ds" %
                                    (time.time() - start_archive))
                    except Exception as e:
                        logger.info(e)
                        import traceback

                        traceback.print_exc()

        return (
            stats_dict["num_val_created"],
            stats_dict["num_val_updated"],
            stats_dict["num_val_ignored"],
            stats_dict["num_path_created"],
            stats_dict["num_path_updated"],
            stats_dict["num_path_ignored"],
        )
Example #52
0
from django.conf import settings

from .models import *
from user.models import *
from utils.logging_dec import logging_check

# Create your views here.
"""
还未接入用户测试
"""

app_private_key_string = open(
    f'{settings.ALIPAY_KEY_DIRS}/app_private_key.pem').read()
alipay_public_key_string = open(
    f'{settings.ALIPAY_KEY_DIRS}/alipay_public_key.pem').read()
r = get_redis_connection('default')  # type:Redis


def crontab(seckill_price, seckill_time, continue_time, count, month):
    """
    当在admin界面创建或者修改秒杀表数据的时候,将调用该函数,在redis中存入该次秒杀的开启时间,价格,和门票总数,和商品总数
    :param seckill_price: 价格
    :param seckill_time: 开启时间
    :param continue_time: 持续时间
    :param count: 商品总数
    :param month: VIP月数(商品详情)
    """
    r.delete('seckills')
    time_now = (seckill_time - timezone.now()).seconds + continue_time
    cache.set('seckill_price', seckill_price, time_now)
    cache.set('seckill_time', seckill_time, time_now)
Example #53
0
def index(request):
    conn = get_redis_connection("default")
    return HttpResponse('设置成功')
Example #54
0
def get_ip_terminal(meetingE164,terminalName,start,count):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_ip_terminal.lua')
    content = fileHandler.read()
    ip_terminal_list = conn.eval(content, 0, meetingE164, terminalName,start,count)
    return json.loads(ip_terminal_list)
Example #55
0
def get_p2p_meeting(parentMoid,meetingName,start,count):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_p2p_meeting_list.lua')
    content = fileHandler.read()
    meeting_list = conn.eval(content, 0, parentMoid,meetingName,start,count)
    return json.loads(meeting_list)
Example #56
0
def save_code(mobile, code):
    # 去连接池中获取一个连接
    conn = get_redis_connection("default")
    conn.set(mobile, code, ex=60)
    return time.time()
Example #57
0
def get_terminal_meeting_score(meetingE164, terminalMoid):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_terminal_meeting_score.lua')
    content = fileHandler.read()
    meeting_score_list = conn.eval(content, 0, meetingE164, terminalMoid)
    return json.loads(meeting_score_list)
Example #58
0
def get_dcs_info(meetingE164, coopState, start, count):
    conn = get_redis_connection()
    fileHandler = open('./nms_server/script/get_dcs_info.lua')
    content = fileHandler.read()
    dcs_info = conn.eval(content, 0, meetingE164, coopState, start, count)
    return json.loads(dcs_info)
Example #59
0
    def get(self, request, type_id, page):
        '''显示列表页'''
        # 获取种类信息(防止用户自主输入不存在的id)
        try:
            type = GoodsType.objects.get(id=type_id)
        except GoodsType.DoesNotExist:
            # 种类不存在
            return redirect(reverse('goods:index'))

        # 获取商品的分类信息
        types = GoodsType.objects.all()

        # 获取排序的方式 # 获取分类商品的信息
        # sort=default 按照默认id排序
        # sort=price 按照商品价格排序
        # sort=hot 按照商品销量排序
        sort = request.GET.get('sort')

        if sort == 'price':
            skus = GoodsSKU.objects.filter(type=type).order_by('price')
        elif sort == 'hot':
            skus = GoodsSKU.objects.filter(type=type).order_by('-sales')
        else:
            sort = 'default'
            skus = GoodsSKU.objects.filter(type=type).order_by('-id')

        # 对数据进行分页
        paginator = Paginator(skus, 1)

        # 获取第page页的内容
        try:
            page = int(page)
        except Exception as e:
            # 如果不是数字,不报错 而是直接默认是第一页
            page = 1

        if page > paginator.num_pages:
            page = 1

        # 获取第page页的Page实例对象
        skus_page = paginator.page(page)

        # 1.总页数小于5页,页面上显示所有页码
        # 2.如果当前页是前3页,显示1-5页
        # 3.如果当前页是后3页,显示后5页
        # 4.其他情况,显示当前页的前2页,当前页,当前页的后2页
        num_pages = paginator.num_pages
        if num_pages < 5:
            pages = range(1, num_pages + 1)
        elif page <= 3:
            pages = range(1, 6)
        elif num_pages - page <= 2:
            pages = range(num_pages - 4, num_pages + 1)
        else:
            pages = range(page - 2, page + 3)

        # 获取新品信息
        new_skus = GoodsSKU.objects.filter(
            type=type).order_by('-create_time')[:2]

        # 获取用户购物车中商品的数目
        user = request.user
        cart_count = 0
        if user.is_authenticated:
            # 用户已登录
            conn = get_redis_connection('default')
            cart_key = 'cart_%d' % user.id
            cart_count = conn.hlen(cart_key)

        # 组织模板上下文
        context = {
            'type': type,
            'types': types,
            'skus_page': skus_page,
            'new_skus': new_skus,
            'cart_count': cart_count,
            'pages': pages,
            'sort': sort
        }

        # 使用模板
        return render(request, 'list.html', context)
Example #60
0
    def create(self, validated_data):
        """
        保存订单
        :param validated_data:
        :return:
        """
        # 获取当前下单用户
        user = self.context['request'].user
        # 创建订单编号
        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ("%09d" % user.id)
        # 保存订单基本数据
        address = validated_data['address']
        pay_method = validated_data['pay_method']
        # 开启事务
        with transaction.atomic():
            # 创建保存点
            save_id = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_amount=Decimal(0),
                    total_count=0,
                    freight=Decimal('10.0'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                    if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNPAID'])

                # 从redis中获取购物车数据
                redis_conn = get_redis_connection('cart')
                cart_redis = redis_conn.hgetall("cart_%s" % user.id)
                cart_selected = redis_conn.smembers('cart_selected_%s' %
                                                    user.id)

                cart = {}
                for sku_id in cart_selected:
                    cart[int(sku_id)] = int(cart_redis[sku_id])
                # sku_obj_list = SKU.objects.filter(id__in=cart.keys())
                # 遍历勾选要下单的商品数据
                sku_id_list = cart.keys()
                for sku_id in sku_id_list:
                    # 判断商品库存
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        origin_stock = sku.stock
                        origin_sales = sku.stock
                        if sku.stock < cart[sku.id]:
                            # 事务回滚
                            transaction.savepoint_rollback(save_id)
                            raise serializers.ValidationError('商品库存不足')
                        # 减少商品库存
                        # sku.stock -= cart[sku.id]
                        # sku.sales += cart[sku.id]
                        # sku.save()
                        new_stock = origin_stock - cart[sku.id]
                        new_sales = origin_sales + cart[sku.id]
                        ret = SKU.objects.filter(id=sku.id,
                                                 stock=origin_stock).update(
                                                     stock=new_stock,
                                                     sales=new_sales)
                        if ret == 0:
                            continue

                        order.total_count += cart[sku.id]
                        order.total_amount += (sku.price * cart[sku.id])
                        # 保存
                        OrderGoods.objects.create(order=order,
                                                  sku=sku,
                                                  count=cart[sku.id],
                                                  price=sku.price)
                        break
                order.save()
            except serializers.ValidationError:
                raise
            except Exception:
                transaction.savepoint_rollback(save_id)
                raise
            # 提交事务
            transaction.savepoint_commit(save_id)

            # 清除购物车已经结算的商品
            pl = redis_conn.pipeline()
            pl.hdel('cart_%s' % user.id, *cart_selected)
            pl.srem('cart_selected_%s' % user.id, *cart_selected)
            pl.execute()
            return order