def get(self, request): code = request.GET.get("code") oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI) try: access_token = oauth.get_access_token(code) openid = oauth.get_open_id(access_token) except: return JsonResponse({"code": 400, "message": "登陆失败"}) try: qq_user = OAuthQQUser.objects.get(openid=openid) except: secret_openid = generate_secret_openid(openid) return JsonResponse({ "code": 300, "message": "OK", "secret_openid": secret_openid }) else: user = qq_user.user login(request, user) response = JsonResponse({"code": 0, "message": "OK"}) response.set_cookie("username", user.username, max_age=14 * 24 * 3600) cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def delete(self, request): """ 购物车记录删除: ① 获取参数并进行校验 ② 根据用户是否登录,删除对应的购物车记录 ③ 返回响应 """ # ① 获取参数并进行校验 req_data = json.loads(request.body) sku_id = req_data.get('sku_id') if not sku_id: return JsonResponse({'code': 400, 'message': '缺少必传参数'}) # ② 根据用户是否登录,删除对应的购物车记录 response = JsonResponse({'code': 0, 'message': '购物车记录删除成功'}) try: cart_helper = CartHelper(request, response) cart_helper.remove_cart(sku_id) except Exception as e: return JsonResponse({'code': 400, 'message': '购物车记录删除失败'}) # ③ 返回响应 return response
def get(self, request): """ 获取QQ登录用户的openid并进行处理 """ # 1.获取code code = request.GET.get('code') # 2.获取QQ登陆用户的openid oauth = OAuthQQ( client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, ) try: # 根据code获取access_token access_token = oauth.get_access_token(code) # 根据access_token获取openid openid = oauth.get_open_id(access_token) except Exception as e: logger.error(e) return JsonResponse({'code': 400, 'message': 'QQ登陆失败'}) # 3.根据openid是否已经和本网站用户进行绑定进行处理 try: qq_user = OAuthQQUser.objects.get(openid=openid) except OAuthQQUser.DoesNotExist: # 如果未进行绑定, 将openid加密并进行返回 secret_openid = generate_secret_openid(openid) return JsonResponse( { 'code': 300, 'message': 'OK', 'secret_openid': secret_openid }, ) else: # 如果已经绑定,保存用户的登陆状态信息 user = qq_user.user login(request, user) response = JsonResponse({ 'code': 0, 'message': 'OK', }) # 设置cookie response.set_cookie( 'username', user.username, max_age=14 * 24 * 3600, ) # 增加代码:合并购物车数据 cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def put(self, request): """ 购物车记录修改: ① 获取参数并进行校验 ② 根据用户是否登录,分别修改购物车记录的数据 ③ 返回响应 """ # ① 获取参数并进行校验 req_data = json.loads(request.body) sku_id = req_data.get('sku_id') count = req_data.get('count') selected = req_data.get('selected', True) if not all([sku_id, count]): return JsonResponse({'code': 400, 'message': '缺少必传参数'}) try: count = int(count) except Exception as e: return JsonResponse({'code': 400, 'message': 'count参数有误'}) if count <= 0: return JsonResponse({'code': 400, 'message': 'count参数有误'}) try: sku = SKU.objects.get(id=sku_id) except Exception as e: return JsonResponse({'code': 400, 'message': 'sku商品不存在'}) # ② 根据用户是否登录,分别修改购物车记录的数据 cart_sku = { 'sku_id': sku_id, 'count': count, 'selected': selected } response = JsonResponse({'code': 0, 'message': '购物车记录修改成功', 'cart_sku': cart_sku}) try: cart_helper = CartHelper(request, response) cart_helper.update_cart(sku_id, count, selected) except Exception as e: return JsonResponse({'code': 400, 'message': '购物车记录修改失败'}) return response
def get(self, request): """订单结算页面""" # ① 获取当前用户的收货地址信息 addresses = Address.objects.filter(user=request.user, is_delete=False) # ② 从redis中获取用户所要结算的商品信息 try: cart_helper = CartHelper(request) cart_data = cart_helper.get_redis_selected_cart() except Exception as e: return JsonResponse({"code": 400, "message": "获取购物车数据失败"}) # ③ 查询数据库获取对应的商品数据 # 商品数据 sku_li = [] try: skus = SKU.objects.filter(id__in=cart_data.keys()) for sku in skus: sku_li.append({ "id": sku.id, "name": sku.name, "default_image_url": "http://192.168.19.131:8888/" + sku.default_image.name, "price": sku.price, "count": cart_data[sku.id] }) except Exception as e: return JsonResponse({"code": 400, "message": "获取商品数据失败"}) freight = Decimal(10.00) address_li = [] try: for address in addresses: address_li.append({ "id": address.id, "province": address.province.name, "city": address.city.name, "district": address.district.name, "place": address.place, "receiver": address.receiver, "mobile": address.mobile }) except Exception as e: return JsonResponse({"code": 400, "message": "地址信息获取错误"}) context = { "addresses": address_li, "skus": sku_li, "freight": freight, "nowsite": request.user.default_address_id } return JsonResponse({"code": 0, "message": "OK", "context": context})
def post(self, request): """ 购物车数据新增: ① 获取参数并进行校验 ② 根据用户是否登录,分别进行购物车数据的保存 ③ 返回响应,购物车记录添加成功 """ # ① 获取参数并进行校验 req_data = json.loads(request.body) sku_id = req_data.get('sku_id') count = req_data.get('count') selected = req_data.get('selected', True) if not all([sku_id, count]): return JsonResponse({'code': 400, 'message': '缺少必传参数'}) try: count = int(count) except Exception as e: return JsonResponse({'code': 400, 'message': 'count参数有误'}) if count <= 0: return JsonResponse({'code': 400, 'message': 'count参数有误'}) try: sku = SKU.objects.get(id=sku_id) except Exception as e: return JsonResponse({'code': 400, 'message': 'sku商品不存在'}) # ② 根据用户是否登录,分别进行购物车数据的保存 response = JsonResponse({'code': 0, 'message': '购物车添加成功', 'count': count}) try: cart_helper = CartHelper(request, response) cart_helper.add_cart(sku_id, count, selected) except Exception as e: return JsonResponse({'code': 400, 'message': '购物车添加失败'}) # ③ 返回响应,购物车记录添加成功 return response
def post(self, request): """ 用户登录 """ # 1.获取参数并进行校验(参数完整性,用户名和密码是否正确) req_data = json.loads(request.body) username = req_data.get('username') password = req_data.get('password') remember = req_data.get('remember') if not all([username, password, ]): return JsonResponse({'code': 400, 'message': '缺少必传参数!'}) # 判断客户端传递的username参数是否符合手机号格式 if re.match(r'^1[3-9]\d{9}$', username): User.USERNAME_FIELD = 'mobile' else: User.USERNAME_FIELD = 'username' # 用户名和密码是否正确 user = authenticate(username=username, password=password) if user is None: return JsonResponse({'code': 400, 'message': '用户名或密码错误!'}) # 2.保存登陆用户的状态信息 login(request, user) if not remember: # 如果未选择记住登录,浏览器关闭即失效 request.session.set_expiry(0) # 3.返回响应 response = JsonResponse({'code': 0, 'message': 'OK'}) # cookie 保存 username 用户名 response.set_cookie('username', user.username, max_age=14 * 24 * 3600) # 增加代码:合并购物车数据 cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def create(self, validated_data): username = validated_data["username"] password = validated_data["password"] mobile = validated_data["mobile"] try: user = User.objects.create_user(username=username, password=password, mobile=mobile) except Exception as e: raise serializers.ValidationError('数据库保存错误') from django.contrib.auth import login login(self.context("request"), user) # ③ 返回响应 response = Response({'code': 0, 'message': 'OK'}) response.set_cookie("username", user.username, max_age=30 * 24 * 3600) cart_helper = CartHelper(self.context("request"), response) cart_helper.merge_cookie_cart_to_redis() return user
def post(self, request): req_data = json.loads(request.body.decode()) mobile = req_data.get("mobile") password = req_data.get("password") sms_code = req_data.get("sms_code") secret_openid = req_data.get("secret_openid") if not all([mobile, password, sms_code, secret_openid]): return JsonResponse({"code": 400, "message": "缺少必传参数"}) if not re.match(r"^1[3-9]\d{9}$", mobile): return JsonResponse({'code': 400, 'message': '请输入正确的手机号码'}) if not re.match(r"^[0-9A-Za-z]{8,20}$", password): return JsonResponse({'code': 400, 'message': '请输入8-20位的密码'}) redis_conn = get_redis_connection("verify_code") sms_code_redis = redis_conn.get("sms_%s" % mobile) if not sms_code_redis: return JsonResponse({"code": 400, "message": "短信验证码已失效"}) if sms_code_redis != sms_code: return JsonResponse({"code": 400, "message": "短信验证码错误"}) openid = check_secret_openid(secret_openid) if not openid: return JsonResponse({'code': 400, 'message': 'secret_openid有误'}) try: user = User.objects.get(mobile=mobile) except: import base64 username = base64.b64encode(mobile.encode()).decode() user = User.objects.create(mobile=mobile, username=username, password=password) else: if not user.check_password(password): return JsonResponse({"code": 400, "message": "登录密码错误"}) try: OAuthQQUser.objects.create(openid=openid, user=user) except Exception as e: print(e) return JsonResponse({'code': 400, 'message': '数据库操作失败'}) login(request, user) response = JsonResponse({'code': 0, 'message': 'OK'}) # 设置cookie response.set_cookie('username', user.username, max_age=3600 * 24 * 14) cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def put(self, request): """ 购物车记录全选和取消全选: ① 获取参数并进行校验 ② 根据用户是否登录,对购物车记录进行全选和取消全选操作 ③ 返回响应 """ # ① 获取参数并进行校验 req_data = json.loads(request.body) selected = req_data.get('selected', True) # ② 根据用户是否登录,对购物车记录进行全选和取消全选操作 response = JsonResponse({'code': 0, 'message': '购物车记录操作成功'}) try: cart_helper = CartHelper(request, response) cart_helper.select_cart(selected) except Exception as e: return JsonResponse({'code': 400, 'message': '购物车记录操作失败'}) # 返回响应 return response
def get(self, request): """ 购物车记录获取: ① 根据用户是否登录,分别进行购物车数据的获取 ② 组织数据并返回响应 """ # ① 根据用户是否登录,分别进行购物车数据的获取 try: cart_helper = CartHelper(request) cart_dict = cart_helper.get_cart() except Exception as e: return JsonResponse({'code': 400, 'message': '购物车获取失败!'}) try: skus = SKU.objects.filter(id__in=cart_dict.keys()) except Exception as e: return JsonResponse({'code': 400, 'message': '获取sku商品信息失败!'}) cart_skus = [] for sku in skus: cart_skus.append({ 'id': sku.id, 'name': sku.name, 'price': sku.price, 'default_image_url': 'http://192.168.19.131:8888/' + sku.default_image.name, 'count': cart_dict[sku.id]['count'], 'selected': cart_dict[sku.id]['selected'], }) return JsonResponse({ 'code': 0, 'message': 'OK', 'cart_skus': cart_skus })
def post(self, request): requ_data = json.loads(request.body) username = requ_data.get("username") password = requ_data.get("password") remember = requ_data.get("remember") if not all([username, password]): return JsonResponse({"code": 400, "message": "缺少必传参数"}) if re.match("^1[3-9]\d{9}$", username): User.USERNAME_FIELD = "mobile" else: User.USERNAME_FIELD = "username" user = authenticate(username=username, password=password) if user is None: return JsonResponse({"code": "400", "message": "账号用户名或密码错误"}) login(request, user) response = JsonResponse({"code": 0, "message": "登录成功"}) if not remember: request.session.set_expiry(0) response.set_cookie("username", user.username) return response response.set_cookie("username", user.username, max_age=30 * 24 * 3600) cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def post(self, request): req_data = json.loads(request.body) address_id = req_data.get("address_id") pay_method = req_data.get("pay_method") if not all([address_id, pay_method]): return JsonResponse({"code": 400, "message": "缺少必传参数"}) try: address = Address.objects.get(id=address_id) except Exception as e: return JsonResponse({"code": 400, "message": "地址信息有误"}) if pay_method not in [1, 2]: return JsonResponse({"code": 400, "message": "支付方式有误"}) user = request.user order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%09d" % user.id total_count = 0 total_amount = 0 if pay_method == 1: status = 2 else: status = 1 freight = Decimal(10.00) # 开启事务 with transaction.atomic(): # 设置数据库操作时, 事务中的保存点 sid = transaction.savepoint() 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) cart_helper = CartHelper(request) cart_dict = cart_helper.get_redis_selected_cart() sku_ids = cart_dict.keys() for sku_id in sku_ids: for i in range(3): sku = SKU.objects.get(id=sku_id) count = cart_dict[sku_id] # 记录原始库存和销量 origin_stock = sku.stock origin_sales = sku.sales print('下单用户:%s 商品库存:%d 购买数量:%d 尝试第 %d 次' % ( user.username, sku.stock, count, i + 1)) if count > sku.stock: # 数据库操作时,撤销事务中指定保存点之后的操作 transaction.savepoint_commit(sid) return JsonResponse({"code": 400, "message": "商品库存不足"}) import time time.sleep(10) # 更新商品库存和销量 new_stock = origin_stock - count new_sales = origin_sales + count # 注意:update 方法返回的是被更新的行数 # update tb_sku set stock=<new_stock>, sales=<news_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 次,仍然失败,报下单失败错误 # 数据库操作时,撤销事务中指定保存点之后的操作 transaction.savepoint_commit(sid) return JsonResponse({"code": 400, "message": "下单失败!"}) continue sku.spu.sales += count sku.spu.save() 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() cart_helper.clear_redis_selected_cart() return JsonResponse({"code": 0, "message": "下单成功", "order_id": order_id})
def post(self, request): """ 绑定QQ登陆用户信息 """ # 1.获取参数并进行校验 req_data = json.loads(request.body) mobile = req_data.get('mobile') password = req_data.get('password') sms_code = req_data.get('sms_code') secret_openid = req_data.get('secret_openid') if not all([mobile, password, sms_code, secret_openid]): return JsonResponse({'code': 400, 'message': '缺少必传参数!'}) # 判断手机号格式是否正确 if not re.match(r'^1[3-9]\d{9}$', mobile): return JsonResponse({'code': 400, 'message': '请输入正确的手机号!'}) # 判断密码是否合格 if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return JsonResponse({'code': 400, 'message': '请输入8-20位的密码!'}) # 短信验证码是否正确 redis_conn = get_redis_connection('verify_code') sms_code_redis = redis_conn.get('sms_%s' % mobile) if not sms_code_redis: return JsonResponse({'code': 400, 'message': '短信验证码已过期!'}) if sms_code != sms_code_redis: return JsonResponse({'code': 400, 'message': '短信验证码错误!'}) # 对access_token进行解密 openid = check_secret_openid(secret_openid) if not openid: return JsonResponse({'code': 400, 'message': 'secret_openid有误!'}) # 2.绑定保存QQ登陆用户信息 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: # 注册信息用户 import base64 # 手机号进行 base64 编码生成用户名 username = base64.b64encode(mobile.encode()).decode() user = User.objects.create_user( username=username, password=password, mobile=mobile, ) else: # 校验密码是否正确 if not user.check_password(password): return JsonResponse({'code': 400, 'message': '登陆密码错误!'}) try: OAuthQQUser.objects.create(openid=openid, user_id=user.id) except Exception as e: logger.error(e) return JsonResponse({'code': 400, 'message': '数据库操作失败!'}) # 返回响应,登陆成功 login(request, user) response = JsonResponse({'code': 0, 'message': 'OK'}) # 设置cookie response.set_cookie( 'username', user.username, max_age=14 * 24 * 3600, ) # 增加代码:合并购物车数据 cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def post(self, request): """ 注册用户信息保存 """ # 1.获取参数并进行校验 req_data = json.loads(request.body) username = req_data.get('username') password = req_data.get('password') password2 = req_data.get('password2') mobile = req_data.get('mobile') allow = req_data.get('allow') sms_code = req_data.get('sms_code') if not all([username, password, password2, mobile, allow, sms_code]): return JsonResponse({'code': 400, 'message': '缺少必传参数'}) if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username): return JsonResponse({'code': 400, 'message': 'username格式错误!'}) if not re.match(r'^[a-zA-Z0-9]{8,20}$', password): return JsonResponse({'code': 400, 'message': 'password格式错误!'}) if password != password2: return JsonResponse({'code': 400, 'message': '两次密码不一致!'}) if not re.match(r'^1[3-9]\d{9}$', mobile): return JsonResponse({'code': 400, 'message': '手机号格式错误!'}) if not allow: return JsonResponse({'code': 400, 'message': '请统一协议'}) # 短信验证码检验 redis_conn = get_redis_connection('verify_code') sms_code_redis = redis_conn.get('sms_%s' % mobile) if not sms_code_redis: return JsonResponse({'code': 400, 'message': '短信验证码过期!'}) if sms_code != sms_code_redis: return JsonResponse({'code': 400, 'message': '短信验证码错误!'}) # 保存新增用户数据到数据库 try: user = User.objects.create_user(username=username, password=password, mobile=mobile) except Exception as e: logger.error(e) return JsonResponse({'code': 400, 'message': '数据库保存错误!'}) # 只要调用login方法,传入request和user对象 # login方法就会将user用户的信息存储到session中 login(request, user) # 返回响应 response = JsonResponse({'code': 0, 'message': 'OK'}) # 设置cookie保存username用户名 response.set_cookie('username', user.username, max_age=14 * 24 * 3600) # 增加代码:合并购物车数据 cart_helper = CartHelper(request, response) cart_helper.merge_cookie_cart_to_redis() return response
def get(self, request): """订单结算页面""" user = request.user try: # ① 获取当前用户的收货地址信息 addresses = Address.objects.filter(user=user, is_delete=False) # 地址信息 address_li = [] for address in addresses: address_li.append({ 'id': address.id, 'province': address.province.name, 'city': address.city.name, 'district': address.district.name, 'place': address.place, 'receiver': address.receiver, 'mobile': address.mobile, }) except Exception as e: return JsonResponse({'code': 400, 'message': '地址信息获取有误'}) # ② 从redis中获取用户所要结算的商品信息 try: cart_helper = CartHelper(request) cart_dict = cart_helper.get_redis_selected_cart() except Exception as e: return JsonResponse({'code': 400, 'message': '获取购物车数据失败'}) # ③ 查询数据库获取对应的商品数据 # 商品数据 sku_li = [] try: skus = SKU.objects.filter(id__in=cart_dict.keys()) for sku in skus: sku_li.append({ 'id': sku.id, 'name': sku.name, 'default_image_url': 'http://192.168.19.131:8888/' + sku.default_image.name, 'price': sku.price, 'count': cart_dict[sku.id] }) except Exception as e: return JsonResponse({'code': 400, 'message': '获取商品数据失败'}) # 订单运费 freight = Decimal(10.00) # ④ 组织并返回响应数据 context = { 'addresses': address_li, 'skus': sku_li, 'freight': freight, 'nowsite': user.default_address_id, } return JsonResponse({'code': 0, 'message': 'OK', 'context': context, })
def post(self, request): """订单创建""" user = request.user # ① 获取参数并进行校验 req_data = json.loads(request.body) address_id = req_data.get('address_id') pay_method = req_data.get('pay_method') if not all([address_id, pay_method]): return JsonResponse({'code': 400, 'message': '缺少必传参数'}) # 地址是否存在 try: address = Address.objects.get(id=address_id, user=user) except Exception as e: return JsonResponse({'code': 400, 'message': '地址信息有误'}) # 1:货到付款 2:支付宝 if pay_method not in (1, 2): return JsonResponse({'code': 400, 'message': '支付方式有误'}) # ② 组织订单数据 # 生成订单id order_id = timezone.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id # total_count和total_amount total_count = 0 total_amount = 0 # 订单状态 if pay_method == 1: # 货到付款:待发货 status = 2 else: # 支付宝:待支付 status = 1 # 运费(此处固定) freight = Decimal(10.00) with transaction.atomic(): # 设置数据库操作时,事务中的保存点 sid = transaction.savepoint() # ③ 向 tb_order_info 数据表中添加一行记录 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) # ④ 遍历用户要购买的商品记录,循环向 tb_order_goods 表中添加记录 # 从 redis 中获取用户要购买的商品信息 cart_helper = CartHelper(request) cart_dict = cart_helper.get_redis_selected_cart() sku_ids = cart_dict.keys() for sku_id in sku_ids: for i in range(3): sku = SKU.objects.get(id=sku_id) count = cart_dict[sku_id] # 记录原始库存和销量 origin_stock = sku.stock origin_sales = sku.sales # 打印下单提示信息 print('下单用户:%s 商品库存:%d 购买数量:%d 尝试第 %d 次' % ( user.username, sku.stock, count, i + 1)) # 判断库存是否充足 if count > sku.stock: # 数据库操作时,撤销事务中指定保存点之后的操作 transaction.savepoint_rollback(sid) return JsonResponse({'code': 400, 'message': '商品库存不足'}) # 进行休眠操作,让 CPU 调度其它进程或线程,模拟订单并发问题 # import time # time.sleep(10) # 更新商品库存和销量 new_stock = origin_stock - count news_sales = origin_sales + count # 注意:update 方法返回的是被更新的行数 # update tb_sku set stock=<new_stock>, sales=<news_sales> # where id=<sku_id> and stock=<origin_stock>; res = SKU.objects.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=news_sales) if res == 0: if i == 2: # 尝试下单更新了 3 次,仍然失败,报下单失败错误 # 数据库操作时,撤销事务中指定保存点之后的操作 transaction.savepoint_rollback(sid) return JsonResponse({'code': 400, 'message': '下单失败!'}) # 更新失败,重新进行尝试 continue # 增加对应SPU商品的销量 sku.spu.sales += count sku.spu.save() # 保存订单商品信息 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() # ⑤ 清除用户购物车中已购买的记录 cart_helper.clear_redis_selected_cart() # ⑥ 返回响应 return JsonResponse({'code': 0, 'message': '下单成功', 'order_id': order_id})