예제 #1
0
    def get(self,request,mobile):
        # 接收
        uuid=request.GET.get('image_code_id')
        image_code=request.GET.get('image_code')

        # 进行sms_code_flage验证
        redis_cli = get_redis_connection('sms_code')
        if redis_cli.get(mobile+'_flage') is not None:
            return http.JsonResponse({
                'code':RETCODE.SMSCODERR,
                'errmsg':'操作频繁,稍后再试'
            })

        # 验证:非空,图形验证码是否正确
        if not all([uuid,image_code]):
            return http.JsonResponse({
                'code':RETCODE.PARAMERR,
                'errmsg':'参数不完整'
            })

        redis_cli = get_redis_connection('image_code')
        image_code_redis=redis_cli.get(uuid)
        if image_code_redis is None:
            return http.JsonResponse({
                'code':RETCODE.IMAGECODEERR,
                'errmsg':'图形验证码过期,点击刷新'
            })
        redis_cli.delete(uuid)

        # 存储在Redis中的数据取出后为二进制数据,不能直接与接收的String类型数据进行对比,
        # 因此要对Redis取出的数据解码操作 .decode(),
        # 以及对两边的字符串同时转换为同样的大小写形式
        if image_code.lower()!=image_code_redis.decode().lower():
            return http.JsonResponse({
                'code':RETCODE.IMAGECODEERR,
                'errmsg':'图形验证码错误'
            })

        # 处理:随机生成6位数
        sms_code='%06d'%random.randint(0,999999)
        # 存入Redis
        redis_cli=get_redis_connection('sms_code')
        # redis_cli.setex(mobile,constants.SMS_CODE_EXPIRES,sms_code)

        # 写发送标记,为了防止短信验证码频发发送,前端的倒计时对于刷新网页的操作无法防止
        # 因此在后端进行验证
        # redis_cli.setex(mobile+'_flage',constants.SMS_CODE_FLAGE_EXPIRES,1)


        # 优化
        # 当需要向Redis写入多条数据时,会与其进行多次交互:效率低
        # 解决:使用 管道 pipeline
        # 实现:先将命令存入管道,再一次性发给redis执行
        redis_pl = redis_cli.pipeline()
        redis_pl.setex(mobile,constants.SMS_CODE_EXPIRES,sms_code)
        redis_pl.setex(mobile+'_flage',constants.SMS_CODE_FLAGE_EXPIRES,1)
        redis_pl.execute()

        # 发送短信
        print(sms_code)

        # 响应
        return http.JsonResponse({
            'code':RETCODE.OK,
            'errmsg':'OK'
        })
예제 #2
0
    def get(self, request, mobile):
        """
        :param mobile: 接收短信的手机号
        :return:
        """
        # 每次发短信验证码之前先拿当前要发短信的手机号获取redis的短信标记,如果没有标记就发,有标记提前响应
        # 创建redis连接对象
        redis_conn = get_redis_connection('verify_code')
        send_flag = redis_conn.get('send_flag_%s' % mobile)

        # 校验标记
        if send_flag:
            return http.JsonResponse({
                'code': RETCODE.THROTTLINGERR,
                'errmsg': '频繁发送短信'
            })

        # 接收到前端传入的mobile, image_code, uuid
        image_code_client = request.GET.get('image_code')
        uuid = request.GET.get('uuid')

        # 判断参数是否齐全
        if all([image_code_client, uuid]) is False:
            return http.JsonResponse({
                'code': RETCODE.NECESSARYPARAMERR,
                'errmsg': '缺少必传参数'
            })

        # 根据uuid作为key 获取到redis中当前用户的图形验证值
        image_code_server = redis_conn.get('img_%s' % uuid)

        # 删除图形验证码,避免恶意测试图形验证码
        redis_conn.delete('img_%s' % uuid)

        # 从redis中取出的数据都是byte类型,需要decode解码
        # 判断用户写的图形验证码和redis存的是否一致
        if image_code_client is None or image_code_client.lower(
        ) != image_code_server.decode().lower():
            return http.JsonResponse({
                'code': RETCODE.IMAGECODEERR,
                'errmsg': '验证码错误'
            })

        # 发送短信
        # 利用随机数生成一个6位数
        sms_code = '%06d' % randint(0, 999999)
        logger.info(sms_code)

        # 创建Redis管道
        pl = redis_conn.pipeline()

        # 将Redis请求添加到队列
        # 将生成好的短信验证码也存储到redis,以备后期校验

        # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)

        # 手机发送验证码后在redis设置一个标记 计时60秒,防止刷新重发

        # redis_conn.setex('send_flag_%s' % mobile, 60, 1)
        pl.setex('send_flag_%s' % mobile, 60, 1)

        # 执行请求

        pl.execute()

        # # 利用SDK容联云发短信
        # CCP().send_template_sms(手机号, [验证码, 提示用户验证码有效期为多少分钟], 短信模版ID)
        # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)

        # 需要把CCP这行代码先加入到一个指定的仓库中,后续在单独的一个线程 进程去异步执行, 不在当下去执行
        # 由生产者 往经纪人里面存任务

        send_sms_code.delay(mobile, sms_code)

        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '短信发送成功'})
예제 #3
0
 def post(self, request):
     #获取参数
     json_data = request.body.decode()
     data = json.loads(json_data)
     sku_id = data.get("sku_id")
     sku_count = data.get("count")
     selected = data.get("selected", True)
     specs = data.get("specs")
     spec = [key + ':' + value for key, value in specs.items()]
     #验证参数
     #判断参数是否齐全
     if not all([sku_id, sku_count]):
         return http.HttpResponseForbidden("参数不全")
     #判断sku是否存在
     try:
         Sku.objects.get(id=sku_id)
     except Sku.DoesNotExist:
         return http.HttpResponseForbidden("商品不存在")
     #判断selected是否为bool
     if selected:
         if not isinstance(selected, bool):
             return http.HttpResponseForbidden("参数有误")
     user = request.user
     #判断用户是否登录
     if user.is_authenticated:  #已登录加入redis4号库
         '''
             user_id:{
                 sku_id1:{
                     count:0,
                 }
                 sku_id2:{
                     count:0,
                 }
             }
             selected:[sku_id1,sku_id2]
         '''
         redis_conn = get_redis_connection("carts")
         pipeline = redis_conn.pipeline()
         pipeline.hincrby("cart_user_%s" % user.id, sku_id, sku_count)
         pipeline.hset("spec_user_%s" % user.id, sku_id, str(spec))
         # pipeline.set("cart_spec_%s" % sku_id, str(spec))
         if selected:
             pipeline.sadd("cart_selected_%s" % user.id, sku_id)
         pipeline.execute()
         # 响应结果
         return http.JsonResponse({'code': 'ok', 'errmsg': '添加购物车成功'})
     else:  #未登录加入cookies中
         '''
             {
                 sku_id1:{
                     count:1,
                     selected:True
                 },
                 sku_id2:{
                     count:1,
                     selected:True
                 }
             }
         '''
         #获取carts的cookies值
         carts_str = request.COOKIES.get("carts")
         if carts_str:  #存在把cookie值转换为字典
             carts_dict = pickle.loads(base64.b64decode(carts_str.encode()))
         else:  #不存在设置cart_dict为空
             carts_dict = {}
         #从购物车中获取sku
         cart_sku = carts_dict.get(sku_id)
         if cart_sku:  #购物车存在这sku则将加数量
             carts_dict[sku_id]['count'] += sku_count
             # carts_dict[sku_id]['selected'] = selected
             # carts_dict[sku_id]['selected'] = selected
         else:  #不存在则添加sku
             carts_dict[sku_id] = {
                 "count": sku_count,
                 "selected": selected,
                 "spec": spec
             }
             #将字典转换成base64的字符串
         carts = base64.b64encode(pickle.dumps(carts_dict)).decode()
         #构造响应
         response = http.JsonResponse({'code': 'ok', 'errmsg': "添加购物车成功"})
         response.set_cookie('carts',
                             carts,
                             max_age=constants.CARTS_COOKIE_EXPIRES)
         return response
예제 #4
0
    def post(self, request):
        """实现地址新增逻辑"""
        #判断是否超过地址上限:最多20个
        user = request.user
        count = Address.objects.filter(user=user, is_deleted=False).count()
        if count >= 20:
            return http.JsonResponse({
                'code': RETCODE.MAXNUM,
                'errmsg': '收货地址超限'
            })

        #接收参数
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        #校验参数
        if all([
                title, receiver, province_id, city_id, district_id, place,
                mobile
        ]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(
                    r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(
                    r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',
                    email):
                return http.HttpResponseForbidden('参数email有误')
        #保存地址信息
        try:
            address = Address.objects.create(user=user,
                                             title=title,
                                             receiver=receiver,
                                             province_id=province_id,
                                             city_id=city_id,
                                             district_id=district_id,
                                             place=place,
                                             mobile=mobile,
                                             tel=tel,
                                             email=email)
        except DatabaseError as e:
            logger.error(e)
            return http.HttpResponseForbidden('添加收货地址失败')
        #设置默认地址
        if user.default_address is None:
            user.default_address = address
            user.save()
        #新增地址成功,将新增地址响应给前段实现局部刷新
        # 把新增的address模型对象转换成字典,并响应给前端
        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province_id': address.province_id,
            'province': address.province.name,
            'city_id': address.city_id,
            'city': address.city.name,
            'district_id': address.district_id,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email,
        }
        #响应保存结果
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': '添加收货地址成功',
            'address': address_dict
        })
예제 #5
0
    def post(self,request):
        """美多商城用户绑定到openid"""

        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        mobile = json_dict.get('mobile')
        password = json_dict.get('password')
        sms_code_client = json_dict.get('sms_code')
        access_token = json_dict.get('access_token')

        # 2.校验参数
        # 判断参数是否齐全
        # if not all([mobile,password,sms_code_client,access_token]):
        #     return http.JsonResponse({'code':400, 'errmsg':'缺少必传参数'})

        if not all([mobile, password, sms_code_client, access_token]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})

        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            return http.JsonResponse({'code': 400, 'errmsg':'请输入正确的手机号码'})

        # 判断密码是否合格
        if not re.match(r'^[0-9a-zA-Z]{8,20}$',password):
            return http.JsonResponse({'code': 400, 'errmsg': '请输入8-20位的密码'})

        # 3.判断短信验证码是否一致
        # 创建 redis 链接对象:
        redis_conn = get_redis_connection('verify_code')
        # 从 redis 中获取 sms_code 值:
        sms_code_server = redis_conn.get('sms_%s' % mobile)

        # 判断获取出来的有没有:
        if not sms_code_server:
            # 如果没有, 直接返回:
            return http.JsonResponse({'code': 400, 'errmsg': '短信验证码失效'})

        # 如果有, 则进行判断:
        if sms_code_client != sms_code_server.decode():
            # 如果不匹配, 则直接返回:
            return http.JsonResponse({'code': 400, 'errmsg': '短信验证码有误'})

        # 校验openid
        openid = check_access_token_openid(access_token)
        if not openid:
            return http.JsonResponse({'code': 400, 'errmsg': '参数openid有误'})

        # 判断手机号对应的手机号是否存在
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            user = User.objects.create_user(username=mobile,password=password,mobile=mobile)
        else:
            if not user.check_password(password):
                return http.JsonResponse({'code': 400, 'errmsg': '密码有误'})


        try:
            OAuthQQUser.objects.create(user=user,openid=openid)
        except Exception as e:
            return http.JsonResponse({'code': 400, 'errmsg': 'QQ登录失败'})

        # 实现状态保持
        login(request=request, user=user)
        response = http.JsonResponse({'code': 0, 'errmsg': 'OK'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

        # 响应结果
        return response
예제 #6
0
    def post(self, request):
        #1,获取参数
        dict_data = json.loads(request.body.decode())
        address_id = dict_data.get("address_id")
        pay_method = dict_data.get("pay_method")

        #2,校验参数
        #2,1 为空校验
        if not all([address_id, pay_method]):
            return http.JsonResponse(status=400)

        #2,2 地址是否存在
        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.JsonResponse(status=400)

        #2,3 支付是否正确
        if pay_method not in [
                OrderInfo.PAY_METHODS_ENUM["CASH"],
                OrderInfo.PAY_METHODS_ENUM["ALIPAY"]
        ]:
            return http.JsonResponse(status=400)

        #3,数据入库
        #3,1 订单编号
        user = request.user
        order_id = timezone.now().strftime(
            "%Y%m%d%H%m%s") + "%06d%s" % (random.randint(0, 999999), user.id)

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

        #TODO 设置保存点
        sid = transaction.savepoint()

        #3,3 创建订单信息对象,入库
        order_info = OrderInfo.objects.create(
            order_id=order_id,
            user=user,
            address=address,
            total_count=0,
            total_amount=Decimal(0.0),
            freight=Decimal(10.0),
            pay_method=pay_method,
            status=status,
        )

        #3,4 获取要结算的商品,并入库
        redis_conn = get_redis_connection("cart")
        cart_dict = redis_conn.hgetall("cart_%s" % user.id)
        selected_list = redis_conn.smembers("selected_%s" % user.id)

        for sku_id in selected_list:
            while True:
                #4,1 获取商品,数量
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict.get(sku_id))

                #4,2 判断库存
                if count > sku.stock:
                    #TODO 回滚
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({"errmsg": "库存不足"})

                #TODO 模拟并发下单
                import time
                time.sleep(5)

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

                #TODO 使用乐观锁解决并发下单
                #4,3,1 准备数据新,老库存
                old_stock = sku.stock
                old_sales = sku.sales

                new_stock = old_stock - count
                new_sales = old_sales + count

                #4,3,2 跟新数据
                ret = SKU.objects.filter(id=sku_id, stock=old_stock).update(
                    stock=new_stock, sales=new_sales)

                #4,3,3 判断是否更新成功
                if ret == 0:
                    # transaction.savepoint_rollback(sid)
                    # return http.JsonResponse({"errmsg":"下单失败"})
                    continue

                #4,4 创建订单商品对象,入库
                OrderGoods.objects.create(
                    order=order_info,
                    sku=sku,
                    count=count,
                    price=sku.price,
                )

                #4,5 累加数量,价格
                order_info.total_count += count
                order_info.total_amount += (count * sku.price)

                #一定要跳出
                break

        #5,提交订单信息
        order_info.save()
        transaction.savepoint_commit(sid)  #TODO 提交事务

        #6,清除redis数据
        redis_conn.hdel("cart_%s" % user.id, *selected_list)
        redis_conn.srem("selected_%s" % user.id, *selected_list)

        #7,返回响应
        return http.JsonResponse({"code": RET.OK, "order_id": order_id})
예제 #7
0
    def get(self, request, mobile):
        """
        :param request:
        :param mobile:手机号
        :return: json
        """
        # 接收参数
        img_code_client = request.GET.get('image_code')
        # print(img_code_client)
        uuid = request.GET.get('uuid')
        # 校验参数
        if not all([img_code_client, uuid]):
            return http.HttpResponseForbidden('缺少必要参数')
        # 创建链接redis的对象
        redis_conn = get_redis_connection('verify_code')

        # 判断用户是否频繁发送短信验证码
        send_flg = redis_conn.get('send_flg_%s' % mobile)
        if send_flg:  # 已经发送过了
            return http.JsonResponse({
                'code': RETCODE.THROTTLINGERR,
                'errmsg': '发送短信过于频繁'
            })

        # 提取图形验证码

        img_code_server = redis_conn.get("img_%s" % uuid)  # 这是一个bytes类型
        if img_code_server is None:
            return http.JsonResponse({
                'code': RETCODE.IMAGECODEERR,
                'errmsg': '图形验证码已经失效'
            })
        # 删除图形验证码
        redis_conn.delete("img_%s" % uuid)
        # 对比图形验证码,将bytes类型转为字符串再比较
        img_code_server = img_code_server.decode()
        if img_code_server.lower() != img_code_client.lower():
            return http.JsonResponse({
                'code': RETCODE.IMAGECODEERR,
                'errmsg': '图形验证码有误'
            })

        # 生产短信验证码 %06d代表,如果不够6位,前面补0
        sms_code = '%06d' % random.randint(0, 999999)
        # 手动输出日志,记录短信验证码
        logger.info(sms_code)
        # # 保存短信验证码
        # redis_conn.setex("sms_%s" % mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
        # # 保存发送短信验证码的标记
        # redis_conn.setex('send_flg_%s' % mobile,constants.SEND_SMS_CODE_INTERVAL,1)

        # 创建redis管道
        pl = redis_conn.pipeline()
        # 将命令添加到队列中
        # 保存短信验证码
        pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # 保存发送短信验证码的标记
        pl.setex('send_flg_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        # 执行
        pl.execute()

        # 发送短信验证码
        CPP().send_message_sms(
            mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60],
            constants.SEND_SMS_TEMPLATE_ID)
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信成功'})
예제 #8
0
    def put(self, request, address_id):
        '''
        接收前端传入的参数, 修改数据库数据, 返回
        :param request:
        :param address_id:
        :return:
        '''
        # 1.接收参数(json)
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 2.校验(整体 + 单个)
        if not all(
            [receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseForbidden('缺少必传参数')

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('手机号格式不正确')

        if tel:
            if not re.match(
                    r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('固定电话格式不正确')

        if email:
            if not re.match(
                    r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',
                    email):
                return http.HttpResponseForbidden('email格式不正确')

        # 3.修改数据库数据
        try:
            result = Address.objects.filter(id=address_id).update(
                user=request.user,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                title=receiver,
                receiver=receiver,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email)
        except Exception as e:
            return http.JsonResponse({
                'code': RETCODE.DBERR,
                'errmsg': '修改数据库出错'
            })

        # print(result)

        address = Address.objects.get(id=address_id)

        # 4.拼接参数, 准备返回
        address_dict = {
            'id': address.id,
            'receiver': address.receiver,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email
        }

        # 5.返回
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': 'ok',
            'address': address_dict
        })
예제 #9
0
    def post(self, request):
        '''
        接收参数, 保存到mysql中, 新增地址
        :param request:
        :return:
        '''
        # 1.判断数据库中是否已经有20个地址了
        # count = request.user.addresses.count()
        # count = request.user.addresses.model.objects.filter(is_deleted=False).count()
        count = request.user.addresses.filter(is_deleted=False).count()
        if count >= 20:
            return http.JsonResponse({
                'code': RETCODE.THROTTLINGERR,
                'errmsg': '超过地址上限'
            })

        # 2.接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 3.校验(整体 + 单个)
        if not all(
            [receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseForbidden('缺少必传参数')

        if not re.match(r'', mobile):
            return http.HttpResponseForbidden('手机号不符合规定')

        if tel:
            if not re.match(r'', tel):
                return http.HttpResponseForbidden('固定电话不符合规定')

        if email:
            if not re.match(r'', email):
                return http.HttpResponseForbidden('email不符合规定')

        province = Area.objects.get(id=province_id)

        try:
            address = Address.objects.create(user=request.user,
                                             province=province,
                                             city_id=city_id,
                                             district_id=district_id,
                                             title=receiver,
                                             receiver=receiver,
                                             place=place,
                                             mobile=mobile,
                                             tel=tel,
                                             email=email)

            # 4.判断是否有默认地址, 如果没有, 把当前地址作为默认地址
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()
        except Exception as e:
            return http.JsonResponse({
                'code': RETCODE.DBERR,
                'errmsg': '保存地址出错'
            })

        # 5.拼接参数, 准备返回
        address_dict = {
            'id': address.id,
            'receiver': address.receiver,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email
        }

        # 6.返回
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': 'ok',
            'address': address_dict
        })
예제 #10
0
 def handle_no_permission(self):
     return http.JsonResponse({
         'code': RETCODE.SESSIONERR,
         'errmsg': '您未登录'
     })
예제 #11
0
파일: views.py 프로젝트: rmoorman/Kiwi
        def remove(self):
            pks = request.POST.getlist('pk')
            bks = Bookmark.objects.filter(pk__in=pks, user=request.user)
            bks.delete()

            return http.JsonResponse(self.ajax_response)
예제 #12
0
    def put(self, request, address_id):
        """修改地址"""
        # 接受请求体数据
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验
        if all([
                title, receiver, province_id, city_id, district_id, place,
                mobile
        ]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(
                    r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(
                    r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',
                    email):
                return http.HttpResponseForbidden('参数email有误')

        # 修改收货地址数据
        try:
            Addresses.objects.filter(id=address_id).update(
                title=title,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email)
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '修改收货地址失败'
            })
        # 获取到修改后的地址模型对象
        address_model = Addresses.objects.get(id=address_id)
        address_dict = {
            'id': address_model.id,
            'title': address_model.title,
            "receiver": address_model.receiver,
            "province": address_model.province.name,
            "province_id": address_model.province.id,
            "city": address_model.city.name,
            "city_id": address_model.city.id,
            "district": address_model.district.name,
            "district_id": address_model.district.id,
            "place": address_model.place,
            "mobile": address_model.mobile,
            "tel": address_model.tel,
            "email": address_model.email
        }
        # 响应
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': 'ok',
            'address': address_dict
        })
예제 #13
0
    def post(self, request):
        # 判断用户的收货地址是否上线
        user = request.user
        # count = user.address.filter(is_deleted=False).count()
        count = Addresses.objects.filter(user=user, is_deleted=False).count()
        if count > 20:
            return http.JsonResponse({
                'code': RETCODE.THROTTLINGERR,
                'errmsg': '收货地址超过上限'
            })
        # 接受请求体数据

        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        # 校验
        if all([
                title, receiver, province_id, city_id, district_id, place,
                mobile
        ]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(
                    r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(
                    r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',
                    email):
                return http.HttpResponseForbidden('参数email有误')
        # 保存收货地址数据
        try:
            address_model = Addresses.objects.create(user=request.user,
                                                     title=title,
                                                     receiver=receiver,
                                                     province_id=province_id,
                                                     city_id=city_id,
                                                     district_id=district_id,
                                                     place=place,
                                                     mobile=mobile,
                                                     tel=tel,
                                                     email=email)
            # 如果当前用户还没有默认收货地址,就把当前新增的这个收货地址设置为它的默认地址
            if not user.default_address:
                user.default_address = address_model
                user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '新增收货地址失败'
            })

        # 把保存好的模型对象转换成字段,再响应给前端
        address_dict = {
            'id': address_model.id,
            'title': address_model.title,
            "receiver": address_model.receiver,
            "province": address_model.province.name,
            "province_id": address_model.province.id,
            "city": address_model.city.name,
            "city_id": address_model.city.id,
            "district": address_model.district.name,
            "district_id": address_model.district.id,
            "place": address_model.place,
            "mobile": address_model.mobile,
            "tel": address_model.tel,
            "email": address_model.email
        }
        # 响应
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': '新增地址成功',
            'address': address_dict
        })
예제 #14
0
 def get(self, request, mobile):
     count = User.objects.filter(mobile=mobile).count()
     if count != 0:
         return http.HttpResponseForbidden('手机号已存在')
     response_data = {'count': count, 'code': RETCODE.OK, 'errmsg': 'OK'}
     return http.JsonResponse(response_data)
예제 #15
0
 def get(self, request):
     # 判断当前是查询省份数据还是市区数据
     area_id = request.GET.get('area_id')
     if not area_id:
         # 读取省份缓存数据
         province_list = cache.get('province_list')
         if not province_list:
             # 查询省份数据
             try:
                 province_model_list = models.Area.objects.filter(
                     parent__isnull=True)
                 province_list = []
                 for province_model in province_model_list:
                     province_dict = {
                         'id': province_model.id,
                         'name': province_model.name
                     }
                     province_list.append(province_dict)
                 # 缓存省份字典列表数据:默认存储到名为'default'的配置中
                 cache.set('province_list', province_list, 3600)
             except Exception as e:
                 logger.error(e)
                 return http.JsonResponse({
                     'code': RETCODE.DBERR,
                     'errmsg': '查询省份数据错误'
                 })
         # 响应省级JSON数据
         return http.JsonResponse({
             'code': RETCODE.OK,
             'errmsg': 'OK',
             'province_list': province_list
         })
     else:
         # 判断是否有缓存
         sub_data = cache.get('sub_area_' + area_id)
         if not sub_data:
             # 查询城市或区县数据
             try:
                 parent_model = models.Area.objects.get(id=area_id)
                 # model_list = parent_model.area_set.all()
                 sub_model_list = parent_model.subs.all()
                 subs = []
                 for sub_model in sub_model_list:
                     sub_dict = {
                         'id': sub_model.id,
                         'name': sub_model.name,
                     }
                     subs.append(sub_dict)
                 sub_data = {
                     'id': parent_model.id,
                     'name': parent_model.name,
                     'subs': subs
                 }
                 # 缓存城市或者区县
                 cache.set('sub_area_' + area_id, sub_data, 3600)
             except Exception as e:
                 logger.error(e)
                 return http.JsonResponse({
                     'code': RETCODE.OK,
                     'errmsg': '查询城市或区县数据错误'
                 })
         return http.JsonResponse({
             'code': RETCODE.OK,
             'errmsg': 'OK',
             'sub_data': sub_data
         })
예제 #16
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)

        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.HttpResponseForbidden("商品不村咋")

        try:
            count = int(count)
        except:
            return http.HttpResponseForbidden('COUNT不是整形')

        if selected:
            if not isinstance(selected, bool):
                return http.HttpResponseForbidden('selected不是bool类型')

        user = request.user

        response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加购物车成功'})

        if user.is_authenticated:
            redis_carts_client = get_redis_connection('carts')

            client_data = redis_carts_client.hgetall(user.id)

            # print('哦按段之前',client_data)

            if str(sku_id).encode() in client_data:
                # print(client_data)
                bytes_carts = client_data[str(sku_id).encode()]
                str_carts = bytes_carts.decode()
                dict_carts = json.loads(str_carts)
                dict_carts['count'] += count

                redis_carts_client.hset(user.id, sku_id,
                                        json.dumps(dict_carts))

            else:
                redis_carts_client.hset(
                    user.id, sku_id,
                    json.dumps({
                        'count': count,
                        "selected": selected
                    }))

        else:
            #weidenglu

            #获取cookie中所有的数据

            cookie_str = request.COOKIES.get('carts')

            if cookie_str:
                carts_dict = CookieSecret.loads(cookie_str)
            else:
                carts_dict = {}
            #解密
            # carts_dict = CookieSecret.loads(cookie_str)

            # 判断是否存在
            if sku_id in carts_dict:
                # carts_dict[sku_id]['count'] += count

                origi_count = carts_dict[sku_id]['count']
                count += origi_count

            carts_dict[sku_id] = {'count': count, 'selected': selected}

            dumps_str = CookieSecret.dumps(carts_dict)

            response.set_cookie('carts', dumps_str, max_age=14 * 24 * 3600)

            #存在 累加
            # 不存在新增

        return response
예제 #17
0
파일: views.py 프로젝트: baixin999/mymd
    def put(self, request):
        # 修改
        # 接收、验证
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected')

        # 验证
        if not all([sku_id, count]):
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '参数不完整'
            })
        # sku_id有效
        try:
            sku = SKU.objects.get(pk=sku_id)
        except:
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '商品编号无效'
            })
        # 数量
        count = int(count)
        if count > 5:
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '购买数量不能超过5个'
            })
        elif count < 1:
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '购买数量不能少于1个'
            })
        elif count > sku.stock:
            return http.JsonResponse({
                'code': RETCODE.PARAMERR,
                'errmsg': '商品库存不足'
            })
        # 选中状态
        # if selected == 'true':
        #     selected = True
        # else:
        #     selected = False

        # 处理、响应
        response = http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': 'OK',
            'cart_sku': {
                'id': sku.id,
                'selected': str(selected),
                'default_image_url': sku.default_image.url,
                'name': sku.name,
                'price': str(sku.price),
                'count': count,
                'total_amount': str(count * sku.price)
            }
        })

        if request.user.is_authenticated:
            # 登录状态,将购物车存入redis
            redis_cli = get_redis_connection('cart')
            # 向hash中存商品编号、数量
            redis_cli.hset('cart%d' % request.user.id, sku_id, count)
            # 向set中存商品编号,表示选中此商品
            if selected:
                redis_cli.sadd('selected%d' % request.user.id, sku_id)
            else:
                redis_cli.srem('selected%d' % request.user.id, sku_id)
        else:
            # 未登录,存入cookie
            # 1.读取cookie中的购物车数据
            cart_str = request.COOKIES.get('cart')
            if cart_str:
                # 如果购物车数据已经存在,则转字典
                cart_dict = meiduo_json.loads(cart_str)
            else:
                # 如果第一次加入购物车数据,则新建字典
                cart_dict = {}

            # 2.向字典中添加或修改数据
            # cart_dict = {
            #     sku_id: {
            #         'count': count,
            #         'selected': True
            #     }
            # }
            cart_dict[sku_id] = {'count': count, 'selected': selected}

            # 3.写cookie
            cart_str = meiduo_json.dumps(cart_dict)
            # cart_str = json.dumps(cart_dict)
            response.set_cookie('cart',
                                cart_str,
                                max_age=constants.CART_COOKIE_EXPIRES)

        return response
예제 #18
0
    def get(self, request):
        area_id = request.GET.get('area_id')

        if not area_id:

            province_list = cache.get('province_list')
            if not province_list:
                try:
                    # 没有area_id,代表是省份
                    province_model_list = Area.objects.filter(
                        parent_id__isnull=True)
                    province_list = []
                    for province in province_model_list:
                        province_dict = {
                            'id': province.pk,
                            'name': province.name
                        }
                        province_list.append(province_dict)

                    cache.set('province_list', province_list, 3600)
                except Exception as e:
                    logger.error(e)
                    return http.JsonResponse({
                        'code': RETCODE.DBERR,
                        'errmsg': '查询省份数据失败'
                    })

            return http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': 'ok',
                'province_list': province_list
            })

        else:

            sub_data = cache.get('sub_area_' + area_id)

            if not sub_data:
                try:
                    # 没有area_id,代表是省份
                    parent_area = Area.objects.get(pk=area_id)
                    sub_area_model = parent_area.subs.all()
                    subs = []
                    sub_data = {
                        'id': parent_area.pk,
                        'name': parent_area.name,
                        'subs': subs
                    }
                    for sub in sub_area_model:
                        subs.append({'id': sub.pk, 'name': sub.name})

                    cache.set('sub_area_' + area_id, sub_data, 3600)

                except Exception as e:
                    logger.error(e)
                    return http.JsonResponse({
                        'code': RETCODE.DBERR,
                        'errmsg': '查询市区数据失败'
                    })

            return http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': 'ok',
                'sub_data': sub_data
            })
예제 #19
0
def model_wrapper(request, model_name):
    if model_name in BLACKLIST:
        raise http.Http404("Don't know what you're talking about!")

    for source in MODELS_MODULES:
        try:
            model = getattr(source, model_name)
            break
        except AttributeError:
            pass
    else:
        raise http.Http404('no service called `%s`' % model_name)

    if not is_valid_model_class(model):
        raise http.Http404('no service called `%s`' % model_name)

    required_permissions = getattr(model(), 'API_REQUIRED_PERMISSIONS', None)
    if isinstance(required_permissions, basestring):
        required_permissions = [required_permissions]
    if (
        required_permissions and
        (
            not request.user.is_active or
            not has_permissions(request.user, required_permissions)
        )
    ):
        permission_names = []
        for permission in required_permissions:
            codename = permission.split('.', 1)[1]
            try:
                permission_names.append(
                    Permission.objects.get(
                        codename=codename
                    ).name
                )
            except Permission.DoesNotExist:
                permission_names.append(codename)
        # you're not allowed to use this model
        return http.JsonResponse({
            'error': "Use of this endpoint requires the '%s' permission" % (
                ', '.join(permission_names),
            )
        }, status=403)

    # it being set to None means it's been deliberately disabled
    if getattr(model, 'API_WHITELIST', False) is False:
        raise APIWhitelistError('No API_WHITELIST defined for %r' % model)

    instance = model()

    # Any additional headers we intend to set on the response
    headers = {}

    # Certain models need to know who the user is to be able to
    # internally use that to determine its output.
    instance.api_user = request.user

    if request.method == 'POST':
        function = instance.post
    else:
        function = instance.get
    if not function:
        return http.HttpResponseNotAllowed([request.method])

    # assume first that it won't need a binary response
    binary_response = False

    request_data = request.method == 'GET' and request.GET or request.POST
    form = FormWrapper(model, request_data)
    if form.is_valid():
        try:
            result = function(**form.cleaned_data)
        except ValueError as e:
            if (
                # built in json module ValueError
                'No JSON object could be decoded' in e or
                # ujson module ValueError
                'Expected object or value' in e
            ):
                return http.HttpResponseBadRequest(
                    json.dumps({'error': 'Not a valid JSON response'}),
                    content_type='application/json; charset=UTF-8'
                )
            raise
        except NOT_FOUND_EXCEPTIONS as exception:
            return http.HttpResponseNotFound(
                json.dumps({'error': unicode(exception)}),
                content_type='application/json; charset=UTF-8'
            )
        except BAD_REQUEST_EXCEPTIONS as exception:
            return http.HttpResponseBadRequest(
                json.dumps({'error': unicode(exception)}),
                content_type='application/json; charset=UTF-8'
            )

        # Some models allows to return a binary reponse. It does so based on
        # the models `BINARY_RESPONSE` dict in which all keys and values
        # need to be in the valid query. For example, if the query is
        # `?foo=bar&other=thing&bar=baz` and the `BINARY_RESPONSE` dict is
        # exactly: {'foo': 'bar', 'bar': 'baz'} it will return a binary
        # response with content type `application/octet-stream`.
        for key, value in model.API_BINARY_RESPONSE.items():
            if form.cleaned_data.get(key) == value:
                binary_response = True
            else:
                binary_response = False
                break

        if binary_response:
            # if you don't have all required permissions, you'll get a 403
            required_permissions = model.API_BINARY_PERMISSIONS
            if isinstance(required_permissions, basestring):
                required_permissions = [required_permissions]
            if (
                required_permissions and
                not has_permissions(request.user, required_permissions)
            ):
                permission_names = []
                for permission in required_permissions:
                    codename = permission.split('.', 1)[1]
                    try:
                        permission_names.append(
                            Permission.objects.get(
                                codename=codename
                            ).name
                        )
                    except Permission.DoesNotExist:
                        permission_names.append(codename)
                # you're not allowed to get the binary response
                return http.HttpResponseForbidden(
                    "Binary response requires the '%s' permission\n" %
                    (', '.join(permission_names))
                )

        elif not request.user.has_perm('crashstats.view_pii'):
            clean_scrub = getattr(model, 'API_CLEAN_SCRUB', None)

            if callable(model.API_WHITELIST):
                whitelist = model.API_WHITELIST()
            else:
                whitelist = model.API_WHITELIST

            if result and whitelist:
                cleaner = Cleaner(
                    whitelist,
                    clean_scrub=clean_scrub,
                    # if True, uses warnings.warn() to show fields
                    # not whitelisted
                    debug=settings.DEBUG,
                )
                cleaner.start(result)

    else:
        # custom override of the status code
        return {'errors': dict(form.errors)}, 400

    if binary_response:
        assert model.API_BINARY_FILENAME, 'No API_BINARY_FILENAME set on model'
        response = http.HttpResponse(
            result,
            content_type='application/octet-stream'
        )
        filename = model.API_BINARY_FILENAME % form.cleaned_data
        response['Content-Disposition'] = (
            'attachment; filename="%s"' % filename
        )
        return response

    if (
        getattr(model, 'deprecation_warning', False)
    ):
        if isinstance(result, dict):
            result['DEPRECATION_WARNING'] = model.deprecation_warning
        # If you return a tuple of two dicts, the second one becomes
        # the extra headers.
        # return result, {
        headers['DEPRECATION-WARNING'] = (
            model.deprecation_warning.replace('\n', ' ')
        )

    if model.cache_seconds:
        # We can set a Cache-Control header.
        # We say 'private' because the content can depend on the user
        # and we don't want the response to be collected in HTTP proxies
        # by mistake.
        headers['Cache-Control'] = 'private, max-age={}'.format(
            model.cache_seconds,
        )

    return result, headers
예제 #20
0
파일: utils.py 프로젝트: vmarreros/hpc
def ___jsonresponse___list___tree___(request, ___utils___module___, ___utils___module_model___):
    try:
        pk = int(request.GET.get('pk'))
        int___parent = int(request.GET.get('parent'))
        int___position = int(request.GET.get('position'))
    except ValueError:
        messages.add_message(request, messages.ERROR, _('APPLICATION___SECURITY___MESSAGE ERROR.'))
        return ___jsonresponse___error___(request=request)
    dict___data = dict()
    instance = ___utils___module_model___.___MODEL___.objects.___instance___(request=request, pk=pk)
    if instance is None:
        messages.add_message(request, messages.ERROR, _('APPLICATION___SECURITY___MESSAGE ERROR.'))
        return ___jsonresponse___error___(request=request)
    if int___parent < 0:
        messages.add_message(request, messages.ERROR, _('APPLICATION___SECURITY___MESSAGE ERROR.'))
        return ___jsonresponse___error___(request=request)
    instance_parent = None
    if 0 < int___parent:  # when int___parent==0: this instance have parent==null in the data base
        instance_parent = ___utils___module_model___.___MODEL___.objects.___instance___(request=request, pk=int___parent)
        if instance_parent is None:
            messages.add_message(request, messages.ERROR, _('APPLICATION___SECURITY___MESSAGE ERROR.'))
            return ___jsonresponse___error___(request=request)
    instances = ___utils___module_model___.___MODEL___.objects.___instances___(request=request)
    if not (0 < int___position <= len(instances)):
        messages.add_message(request, messages.ERROR, _('APPLICATION___SECURITY___MESSAGE ERROR.'))
        return ___jsonresponse___error___(request=request)
    # get parents of instance
    list_int___parent = []
    temporal_int___parent = instance.parent
    while temporal_int___parent != 0:
        list_int___parent.append(temporal_int___parent)
        temporal_instance___parent = ___utils___module_model___.___MODEL___.objects.___instance___(request=request, pk=temporal_int___parent)
        temporal_int___parent = temporal_instance___parent.parent
    list_int___parent.append(0)
    # count children of the instance
    int___children_amount = 0
    for temporal_instance in instances[instance.position:]:
        if temporal_instance.parent in list_int___parent:
            break
        int___children_amount += 1
    # change positions
    if instance.position < int___position:
        for temporal_instance in instances[instance.position + int___children_amount:int___position + int___children_amount]:
            temporal_instance.position -= (1 + int___children_amount)
            temporal_instance.save()
        instances[instance.position - 1].parent = int___parent
        temporal_int___position = int___position
        for temporal_instance in instances[instance.position - 1:instance.position + int___children_amount]:
            temporal_instance.position = temporal_int___position
            temporal_int___position += 1
            temporal_instance.save()
    elif int___position < instance.position:
        instances[instance.position - 1].parent = int___parent
        temporal_int___position = int___position
        for temporal_instance in instances[instance.position - 1:instance.position + int___children_amount]:
            temporal_instance.position = temporal_int___position
            temporal_int___position += 1
            temporal_instance.save()
        for temporal_instance in instances[int___position - 1:instance.position - 1]:
            temporal_instance.position += (int___children_amount + 1)
            temporal_instance.save()
    else:  # instance.position == position
        instances[instance.position - 1].parent = int___parent
        instances[instance.position - 1].save()
    # change is_active
    if 0 < int___parent:  # when int___parent==0: this instance have parent==null in the data base
        if instance_parent.is_active is False and instance.is_active is True:
            instances = ___utils___module_model___.___MODEL___.objects.___instances___(request=request)
            for temporal_instance in instances[int___position - 1:int___position + int___children_amount]:
                temporal_instance.is_active = False
                temporal_instance.save()
            dict___data['LOCALE___is_active'] = dict()
            dict___data['LOCALE___is_active']['option_no'] = '%s' % (_('APPLICATION___ADMINISTRATION___CONTENT___OPTION_NO'),)
    #
    if hasattr(___utils___module_model___, '___void___list___tree___'):
        instance = ___utils___module_model___.___MODEL___.objects.___instance___(request=request, pk=pk)
        ___utils___module_model___.___void___list___tree___(request=request, dict___data=dict___data, instance=instance)
    #
    messages.add_message(request, messages.SUCCESS, _('APPLICATION___ADMINISTRATION___CONTENT___MESSAGE %(instance)s was successfully updated.') % {'instance': instance, })
    dict___data['___HTML___APPLICATION___ADMINISTRATION___MODAL___'] = ___html___template_modal___message___(request=request)
    dict___data['___HTML___APPLICATION___ADMINISTRATION___MODAL___MESSAGE___'] = ___html___template_message___(request=request)
    dict___data['___BOOLEAN___ERROR___'] = False
    return http.JsonResponse(dict___data)
예제 #21
0
    def post(self, request):
        """保存订单信息和订单商品信息"""

        # 获取当前要保存的订单信息
        user = request.user
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        # 校验
        if all([address_id, pay_method]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('address不存在')

        if int(pay_method) not in OrderInfo.PAY_METHODS_ENUM.values():
            return http.HttpResponseForbidden('付款方式有误')

        # 生成订单编号 年月日时分秒+user.id
        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)

        # 订单状态
        status = OrderInfo.ORDER_STATUS_ENUM['UNPAID'] \
                if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] \
                else OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT']

        # 开启事物
        with transaction.atomic():
            # 创建保存点
            save_id = transaction.savepoint()
            # 暴力回滚
            try:
                # 保存生成订单

                order = OrderInfo.objects.create(

                    user = user,
                    order_id = order_id,
                    address = address,
                    total_count = 0,
                    total_amount = Decimal('0.00'),
                    freight = Decimal('10.00'),
                    pay_method = pay_method,
                    status=status
                )
                # 连接redis服务器
                redis_coon = get_redis_connection('carts')

                # 获取hash 和 set 中所有数据
                redis_cart = redis_coon.hgetall('carts_%s' % user.id)

                cart_selected = redis_coon.smembers('selected_%s' % user.id)

                cart_dict = {}
                # 遍历set把要购买的sku_id和count包装到一个新字典中 组建新的已勾选{sku_id:count} 字典
                for sku_id_bytes in cart_selected:

                    cart_dict[int(sku_id_bytes)] = int(redis_cart[sku_id_bytes])
                # 遍历用来包装所有要购买商品的字典
                for sku_id in cart_dict.keys():
                    while True:
                    # 通过sku_id获取到sku模型
                        sku = SKU.objects.get(id=sku_id)
                        # 获取当前商品要购买的数量
                        buy_count = cart_dict[sku_id]
                        # 获取当前商品的库存和销量
                        origin_stock = sku.stock
                        origin_sales = sku.sales

                        # 判断库存
                        if buy_count > origin_stock:
                            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '库存不足'})

                        # 对数据库中库存和销量进行计算 并修改
                        new_stock = origin_stock - buy_count
                        new_sales = origin_sales + buy_count
                        # sku.stock = new_stock
                        # sku.sales = new_sales
                        # sku.save()
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
                        # 如果下单失败,但是库存足够时,继续下单,直到下单成功或者库存不足为止
                        if result == 0:
                            continue

                        sku.spu.sales += buy_count
                        sku.spu.save()

                        # 存储订单商品记录
                        OrderGoods.objects.create(

                            order = order,
                            sku = sku,
                            count = buy_count,
                            price = sku.price
                        )
                        order.total_count += buy_count
                        order.total_amount += (order.total_count * sku.price)
                        # 下单成功或失败跳出循环
                        break
                order.total_amount += order.freight
                order.save()
            except Exception as e:
                # 报错即回滚
                transaction.rollback(save_id)

                # 订单提交成功,提交事物
                transaction.savepoint_commit(save_id)
                # 删除已购买数据
            pl = redis_coon.pipeline()

            pl.hdel('carts_%s' % user.id,*cart_selected)
            pl.delete('selected_%s' % user.id)
            pl.execute()
            # 响应
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'order_id': order_id})
예제 #22
0
    def put(self, request):
        """
                一 把需求写下来 (前端需要收集什么 后端需要做什么)
                    前端 收集修改的sku_id, count, selected传递给后端, 发送ajax请求
                    后端 从数据库/cookie里面更新数据,并且返回
                二 把大体思路写下来(后端的大体思路)
                    1.接收数据
                    2.验证数据
                    3.获取用户的信息
                    4.登陆用户更新redis数据
                        4.1 连接redis
                        4.2 hash
                        4.3 set
                        4.4 返回相应
                    5.未登录更新cookie数据
                        5.1 获取cart数据,并判断
                        5.2 更新指定数据
                        5.3 对字典数据进行处理,并设置cookie
                        5.4 返回相应
                三 把详细思路完善一下(纯后端)
                    1. 接收数据(sku_id, count, selected)
                    2. 验证数据
                    3. 获取用户的信息
                    4. 登录用户更新redis数据
                        hash
                        set
                    5. 非登录用户更新cookie信息
                        carts: {sku_id1: {'count': xxx, 'selected: xxx}, sku_id2:{.........}}

                    6. 返回响应
                四 确定我们请求方式和路由
                    PUT   carts/
                """

        # 1.接收数据
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected')
        # 2.验证数据
        # 2.1 是否有空值
        if not all([sku_id, count]):
            return http.JsonResponse({
                'cdoe': RETCODE.NODATAERR,
                'errmsg': '参数不齐全'
            })
        # 2.2 判断商品是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({
                'cdoe': RETCODE.NODATAERR,
                'errmsg': '商品不存在'
            })
        # 2.3 判断传入的数量是否为数值
        try:
            count = int(count)
        except Exception as e:
            return http.JsonResponse({
                'cdoe': RETCODE.NODATAERR,
                'errmsg': '参数错误'
            })
        # 3.获取用户的信息
        if request.user.is_authenticated:
            # 4.登陆用户更新redis数据
            #     4.1 连接redis
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            #     4.2 hash   user_id  sku_id: count
            pl.hset('carts_%s' % request.user.id, sku_id, count)
            pl.execute()
            #     4.3 set    selected_user_id: selected_id
            # 这里的原则就是:如果勾选,则将sku_id加进集合(集合是无重复),如果没有勾选,则从集合中原有的进行删除
            if selected:
                pl.sadd('selected_%s' % request.user.id, sku_id)
            else:
                # todo 这里原来就是未勾选怎么办?----------------------------------------------------
                pl.srem('selected_%s' % request.user.id, sku_id)
            #     4.4 返回相应
            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'amount': count * sku.price
            }
            return http.JsonResponse({
                'code': RETCODE,
                'errmsg': 'ok',
                'cart_sku': cart_sku
            })
        # 5.未登录更新cookie数据
        else:
            #     5.1 获取cart数据,并判断
            cart_cookie = request.COOKIES.get('carts')
            # todo ==========================================================================
            print(type(cart_cookie))
            # carts: sku_id: {'count': count, 'selected': xxx },.........
            # 判断cart_cookie是否为空,为空则初始化一个空字典, 不为空的话进行解码
            if cart_cookie is None:
                carts = {}
            else:
                carts = pickle.loads(base64.b64decode(cart_cookie))
            #     5.2 更新指定数据
            if sku_id in carts:
                carts[sku_id] = {'count': count, 'selected': selected}
                # carts[sku_id]['count'] = count
                # carts[sku_id]['selected'] = selected
            en = base64.b64encode(pickle.dumps(carts))
            #     5.3 对字典数据进行处理,并设置cookie
            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': 'ok',
                'cart_sku': cart_sku
            })
            response.set_cookie('carts', en)
            #     5.4 返回相应
            return response
예제 #23
0
    def put(self, request, address_id):
        """修改地址业务逻辑"""
        #校验address_id
        try:
            address = Address.objects.get(id=address_id,
                                          user=request.user,
                                          is_deleted=False)
            print(address)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('修改收货地址失败')
        # 接收参数
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if all([
                title, receiver, province_id, city_id, district_id, place,
                mobile
        ]) is False:
            return http.HttpResponseForbidden('缺少必要参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(
                    r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(
                    r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',
                    email):
                return http.HttpResponseForbidden('参数email有误')
        #判断地址是否存在,并更新地址信息
        try:
            address.title = title
            address.receiver = receiver
            address.province_id = province_id
            address.city_id = city_id
            address.district_id = district_id
            address.place = place
            address.mobile = mobile
            address.tel = tel
            address.email = email
            address.save()
        except DatabaseError as e:
            logger.error(e)
            return http.HttpResponseForbidden('修改收获地址失败')

        #构造响应数据
        #把新增的address模型对象转换成字典,并响应给前端
        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province_id': address.province_id,
            'province': address.province.name,
            'city_id': address.city_id,
            'city': address.city.name,
            'district_id': address.district_id,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email,
        }
        #响应更新地址结果
        # return http.JsonResponse({'code':RETCODE.OK,'errmsg':'修改收货地址成功','address':address_dict})
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': '修改收货地址成功',
            'address': address_dict
        })
예제 #24
0
    def delete(self, request):
        """
        一 把需求写下来 (前端需要收集什么 后端需要做什么)
            前端  传要删除的sku_id
            后端  删除数据
        二 把大体思路写下来(后端的大体思路)
            1.接收数据 sku_id
            2.根据用户信息进行判断
            3.登陆用户删除redis
                3.1 连接redis
                3.2 hash
                3.3 set
                3.4 返回相应
            4.未登陆用户删除cookie
                4.1 读取cookie中的数据,并且判断
                4.2 删除数据
                4.3 字典数据处理,并设置cookie
                4.4 返回相应
        三 把详细思路完善一下(纯后端)
            1. 接收数据 sku_id
            2. 校验数据 看有没有这个商品
            3. 判断用户是否登录
            4. 登录用户
                链接redis
                hash
                set
                返回响应
            5. 未登录用户
                读取cookie中的数据,看是否有值
                删除后进行加密
                组织响应数据
                设置cookie
                返回响应
        四 确定我们请求方式和路由
            DELETE  carts/
        """

        # 1.接收数据
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        # 2.根据用户信息进行判断
        user = request.user
        if user.is_authenticated:
            # 3.登陆用户删除redis
            #     3.1 连接redis
            redis_conn = get_redis_connection('carts')
            #    3.2 hash
            redis_conn.hdel('carts_%s' % request.user.id, sku_id)
            #    3.3 set
            redis_conn.srem('selected_%s' % request.user.id, sku_id)
            #    3.4 返回相应
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})
        else:
            # 4.未登陆用户删除cookie  carts { sku_id1:{'count': xxx, 'selected': xxx}, sku_id2:}
            #     4.1 读取cookie中的数据,并且判断
            cookie_data = request.COOKIES.get('carts')
            if cookie_data is None:
                carts = {}
            else:
                carts = pickle.loads(base64.b64decode(cookie_data))
            if sku_id in carts:
                # 4.2 删除字典里面的数据
                del carts[sku_id]
            en = base64.b64encode(pickle.dumps(carts))
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})
            response.set_cookie('carts', en)
            # 4.3 返回响应
            return response
예제 #25
0
파일: folder.py 프로젝트: vishwa58/editor
 def form_invalid(self, form):
     if self.request.is_ajax():
         return http.JsonResponse(form.errors, status=400)
예제 #26
0
    def post(self, request):
        """
        1.需求
                    前端: 收集信息(商品id, 数量count, 选中状态是可选的,默认为选中)
                        如果用户登录了,则请求中携带session_id
                        如果用户没有登录,请求不带session_id
                    后端: 增加数据到购物车
                2.大体思路
                    接收数据
                    验证数据
                    存储数据
                    返回响应
                3.详细思路
                    1.接收数据(sku_id, count)
                    2.验证数据
                    3.根据用户是否登录来判断存储数据的位置和细节
                    4.登录用户redis里面
                        4.1 链接redis
                        4.2 存储(hash,set)
                        4.3 返回响应
                    5.非登录用户 cookie里面
                        5.1 转为二进制
                        5.2 加密
                        5.3 存在cookie里面
                        5.4 返回响应
                4.请求方式和路由
                    POST   carts/
        """

        # 1.接收数据(sku_id, count)
        json_data = json.loads(request.body.decode())
        sku_id = json_data.get('sku_id')
        count = json_data.get('count')

        # 2.验证数据
        # 2.1 判断参数是否齐全
        if not all([sku_id, count]):
            return http.JsonResponse({
                'code': RETCODE.NODATAERR,
                'errmsg': '参数不齐'
            })
        # 2.2 判断是否存在此商品
        try:
            SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({
                'code': RETCODE.NODATAERR,
                'errmsg': '商品不存在'
            })
        # 2.3 传过来的count数量需要是数值而不是字符串
        try:
            count = int(count)
        except Exception as e:
            return http.JsonResponse({
                'code': RETCODE.NODATAERR,
                'errmsg': '商品数量参数错误'
            })

        # 3.根据用户是否登录来判断存储数据的位置和细节
        if request.user.is_authenticated:
            # 4.登录用户redis里面
            # 4.1链接redis
            redis_conn = get_redis_connection('carts')

            # 创建管道
            pl = redis_conn.pipeline()

            # 4.2存储(hash, set)
            # HSET key field value
            # 将哈希表key中的域field的值设为value 。
            # pl.hset('carts_%s' % request.user.id, sku_id, count)
            # todo 这里需要注意.如果这样写的话,再次往购物车加之前加过得商品.不会累计数量,只会覆盖原有数量
            # 所以不满足要求,这里可以使用哈希类型自带的hincrby(),实现在原有基础上,进行加本次的数据操作
            pl.hincrby('carts_%s' % request.user.id, sku_id, count)
            # SADD key member[member...]
            # 将一个或多个member元素加入到集合key当中,已经存在于集合的member元素将被忽略。
            pl.sadd('selected_%s' % request.user.id, sku_id)

            # 执行管道
            pl.execute()

            # 4.3返回响应
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})
        else:
            # 5.非登录用户cookie里面

            # # 5.1 组织数据
            # carts = {
            #     sku_id: {'count': count, 'selected': True},
            # }

            # 这里需要进行判断, 先判断cookie里面的carts是否存在
            cookie_str = request.COOKIES.get('carts')

            if cookie_str is None:
                # 如果不存在,则进行增加
                # 如果cookie数据不存在,先初始化一个 空的carts
                carts = {}
            else:
                # 如果存在.对数据进行解码,并更新count数据
                # 对数据进行base64解码
                de = base64.b64decode(cookie_str)
                # 再将bytes类型的数据转换为字典
                carts = pickle.loads(de)

            if sku_id in carts:
                origin_count = carts[sku_id]['count']
                count = count + origin_count
            carts[sku_id] = {'count': count, 'selected': True}

            # 5.2 加密
            # 将数据转换为bytes类型
            a = pickle.dumps(carts)
            # 将bytes类型转换为base64类型
            b = base64.b64encode(a)
            # 5.3 存在cookie里面
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})
            # todo 这里注意设置cookie时: set_cookie(key,string_value) 里面第二个值应为字符串
            # 而base64为bytes类型的数据,所以要对其进行解码
            response.set_cookie('carts', b.decode())

            # 5.4返回响应
            return response
예제 #27
0
    def put(self, request):
        # 获取参数
        json_data = request.body.decode()
        data = json.loads(json_data)
        sku_id = data.get("sku_id")
        sku_count = data.get("count")
        sku_price = data.get("price")
        sku_amount_price = str(float(sku_price) * int(sku_count))
        sku_amount_price = str(
            Decimal(sku_amount_price).quantize(Decimal("0.00")))
        selected = data.get("selected", True)
        if not all([sku_id, sku_count]):
            return http.HttpResponseForbidden("参数不全")
        # 判断sku是否存在
        try:
            Sku.objects.get(id=sku_id)
        except Sku.DoesNotExist:
            return http.HttpResponseForbidden("商品不存在")
        user = request.user
        # 判断用户是否登录
        if user.is_authenticated:  # 已登录加入redis4号库
            redis_conn = get_redis_connection("carts")
            pipeline = redis_conn.pipeline()
            #直接覆盖当前用户sku的数量
            pipeline.hset("cart_user_%s" % user.id, sku_id, sku_count)
            if selected:  #如果选中,添加
                pipeline.sadd("cart_selected_%s" % user.id, sku_id)
            else:  #没选中,删除
                pipeline.srem("cart_selected_%s" % user.id, sku_id)
            pipeline.execute()
            # 响应结果
            cart_sku = {
                "sku_id": sku_id,
                "count": sku_count,
                "selected": selected,
                "sku_amount_price": sku_amount_price
            }
            return http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': '修改购物车成功',
                'cart_sku': cart_sku
            })
        else:  # 未登录加入cookies中
            # 获取carts的cookies值
            carts_str = request.COOKIES.get("carts")
            if carts_str:  # 存在把cookie值转换为字典
                carts_dict = pickle.loads(base64.b64decode(carts_str.encode()))
            else:  # 不存在设置cart_dict为空
                carts_dict = {}
            # 从购物车中获取sku
            cart_sku = carts_dict.get(sku_id)
            if cart_sku:  # 购物车存在这sku则将覆盖
                carts_dict[sku_id]['count'] = sku_count
                carts_dict[sku_id]['selected'] = selected
            else:  # 不存在则添加sku
                carts_dict[sku_id] = {
                    "count": sku_count,
                    "selected": selected,
                }
                # 将字典转换成base64的字符串
            carts = base64.b64encode(pickle.dumps(carts_dict)).decode()

            # 构造响应数据
            cart_sku = {
                "sku_id": sku_id,
                "count": sku_count,
                "selected": selected,
                "sku_amount_price": sku_amount_price
            }
            response = http.JsonResponse({
                'code': RETCODE.OK,
                'errmsg': '修改购物车成功',
                'cart_sku': cart_sku
            })
            response.set_cookie('carts',
                                carts,
                                max_age=constants.CARTS_COOKIE_EXPIRES)
            return response
예제 #28
0
 def process_exception(self, request, exception):
     if request.environ.get('CONTENT_TYPE') == 'application/json':
         return http.JsonResponse(data={'error': exception.message},
                                  content_type='application/json',
                                  status=400,
                                  charset='utf-8')
예제 #29
0
    def get(self, request, mobile):

        # 来发短信之前先判断此手机号有没有在60s之前发过
        # 0. 创建redis连接对象
        redis_conn = get_redis_connection('verify_code')
        # 尝试性去获取此手机号是否有发过短信的标记
        send_flag = redis_conn.get('send_flag_%s' % mobile)
        # 如果胡提前响应
        if send_flag:
            return http.JsonResponse({
                'code': RETCODE.THROTTLINGERR,
                'errmsg': '频繁发送短信'
            })

        # 1.接收前端传入的数据
        image_code_client = request.GET.get('image_code')
        uuid = request.GET.get('uuid')

        # 2.校验数据
        if all([image_code_client, uuid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        # 2.2 获取redis中的图形验证码
        image_code_server = redis_conn.get("img_%s" %
                                           uuid)  # 从redis获取出来的数据都是bytes类型

        # 2.3 把redis中图形验证码删除
        redis_conn.delete(uuid)  # 只让图形验证码使用一次
        # 2.4 判断短信验证码是否过期
        if image_code_server is None:
            return http.HttpResponseForbidden('图形验证码过期')
        # 2.5 注册必须保证image_code_server它不会None再去调用decode
        print("aaa")
        image_code_server = image_code_server.decode()
        # 2. 6 判断用户输入验证码是否正确 注意转换大小写
        if image_code_client.lower() != image_code_server.lower():
            return http.HttpResponseForbidden('图形验证码输入有误')

        # 3. 随机生成一个6位数字作为验证码
        sms_code = '%06d' % randint(0, 999999)

        logger.info(sms_code)

        # redis管道技术
        pl = redis_conn.pipeline()
        # 将短信验证码存储到redis,以备后期注册时校验
        # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)

        # 向redis多存储一个此手机号已发送过短信的标记,此标记有效期60秒
        # redis_conn.setex('send_flag_%s' % mobile, 60, 1)
        pl.setex('send_flag_%s' % mobile, 60, 1)

        # 执行管道
        pl.execute()

        # 给当前手机号发短信
        # CCP().send_template_sms(要收短信的手机号, [短信验证码, 短信中提示的过期时间单位分钟], 短信模板id)
        # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], 1)
        send_sms_code.delay(mobile, sms_code)  # 生产任务
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信验证码成功'})
예제 #30
0
파일: views.py 프로젝트: xzlee2020/-
    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 Exception:
            return http.HttpResponseForbidden('参数address_id错误')
        if pay_method not in [
                OrderInfo.PAY_METHODS_ENUM['CASH'],
                OrderInfo.PAY_METHODS_ENUM['ALIPAY']
        ]:
            return http.HttpResponseForbidden('参数pay_method错误')
        #获取用户
        user = request.user
        '''保存订单信息'''
        #生成订单号
        order_id = timezone.localtime().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读取购物车中被勾选的商品信息
        redis_conn = get_redis_connection('carts')
        redis_cart = redis_conn.hgetall('carts_%s' % user.id)
        selected = redis_conn.smembers('selected_%s' % user.id)
        carts = {}
        for sku_id in selected:
            carts[int(sku_id)] = int(redis_cart[sku_id])
        sku_ids = carts.keys()
        #遍历购物车中被勾选商品信息
        for sku_id in sku_ids:
            # 查询SKU信息
            sku = SKU.objects.get(id=sku_id)
            # 判断SKU库存
            sku_count = carts[sku.id]
            if sku_count > sku.stock:
                return http.JsonResponse({
                    'code': RETCODE.STOCKERR,
                    'errmsg': '库存不足'
                })

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

            # 修改SPU销量
            spu = SPU.objects.get(id=sku.spu_id)
            spu.sales += sku_count
            spu.save()

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

            # 保存商品订单中总价和总数量
            order.total_count += sku_count
            order.total_amount += (sku_count * sku.price)

        # 添加邮费和保存订单信息
        order.total_amount += order.freight
        order.save()
        # 清除购物车中已结算的商品
        pl = redis_conn.pipeline()
        pl.hdel('carts_%s' % user.id, *selected)
        pl.srem('selected_%s' % user.id, *selected)
        pl.execute()

        # 响应提交订单结果
        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': '下单成功',
            'order_id': order.order_id
        })