1 实现添加购物车的功能
前端的页面如下:
前端的页面分析:
要实现添加购物车的功能,前端要向后端传送的数据有商品的id和添加的数量,并且后端规定以post的方式发送给后端.
后端视图函数的业务逻辑
1 判断用户是否登陆,没登陆返回用户未登录
2 接受前端传来的参数
3 对参数进行校验,判断是否有空的参数,有为空的参数返回参数不完整
4 对传过来的商品id进行数据库查询,看数据库中是否有这个商品存在,没有返回商品不存在
5 对参数添加购物车的数量的类型判断,如果不是整数,返回参数错误
6 判断是否超过库存的数量,返回超过库存不足
7 业务逻辑处理,将购物车数据保存到redis中
如果redis中不存在,则直接将数据保存到redis的购物车中
如果redis中原本包含了这个商品的数量信息, 进行数量累加,在保存到redis中 通过返回json数据,告知前端处理的结果
8 将最新的购物车信息设置到redis中
=======================================================
前端的post请求:
window.location.href = "/users/login"; js中的重定向
post请求必须带 csrfmiddlewaretoken: "{{ csrf_token }}" 否则回报403访问被禁止的错误
前端post请求的代码如下:
$('#add_cart').click(function(){
var req_data = {
sku_id: $(this).attr("sku_id"),
count: $("#num_show").val(),
csrfmiddlewaretoken: "{{ csrf_token }}"
};
// 向后端发送添加购物车的请求
$.post("/cart/add", req_data, function (resp_data) {
if (1 == resp_data.code) {
// 后端表示用户未登录
window.location.href = "/users/login";
} else if (0 == resp_data.code) {
// 添加成功
$(".add_jump").stop().animate({
'left': $to_y+7,
'top': $to_x+7},
"fast", function() {
$(".add_jump").fadeOut('fast',function(){
$('#show_count').html(resp_data.cart_num);
});
});
} else {
alert(resp_data.message);
}
}, "json")
});
请求处理的视图函数:
# /cart/add class AddCartView(View): """添加购物车""" def post(self, request): # 判断用户是否登录 if not request.user.is_authenticated(): # 表示用户未登录 return JsonResponse({"code": 1, "message": "用户未登录"}) # sku_id 商品id # count 商品数量 # 接受参数 sku_id = request.POST.get("sku_id") count = request.POST.get("count") # 校验参数 if not all([sku_id, count]): return JsonResponse({"code": 2, "message": "参数不完整"}) # 判断商品存在与否 try: sku = GoodsSKU.objects.get(id=sku_id) except GoodsSKU.DoesNotExist: # 表示商品不存在 return JsonResponse({"code": 3, "message": "商品不存在"}) # 判断用户请求的count是不是整数 try: count = int(count) except Exception: # 数量不是整数 return JsonResponse({"code": 4, "message": "参数错误"}) # 判断数量有没有超过库存 if count > sku.stock: return JsonResponse({"code": 5, "message": "库存不足"}) # 业务逻辑处理,将数据保存到redis中 # {"sku_1": 10, "sku_2": 20} redis_conn = get_redis_connection("default") # 先从redis中尝试获取用户原有购物车中相同商品的信息 user_id = request.user.id origin_count = redis_conn.hget("cart_%s" % user_id, sku_id) # 如果redis中不存在,则直接将数据保存到redis的购物车中 # 如果redis中原本包含了这个商品的数量信息, 进行数量累加,在保存到redis中 if origin_count is not None: count += int(origin_count) # 在把新的购物信息设置会 redis中 redis_conn.hset("cart_%s" % user_id, sku_id, count) cart_num = 0 cart =redis_conn.hgetall('cart_%s' %user_id) for val in cart.values(): cart_num +=int(val) # 通过返回json数据,告知前端处理的结果 return JsonResponse({"code": 0, "message": "添加购物车成功",'cart_num':cart_num})
url的根级的请求路径:
url(r'^cart/', include(cart.urls, namespace="cart")),
在cart应用中的uri的请求路径
from cart import views urlpatterns = [ url(r"^add$", views.AddCartView.as_view(), name="add"), ]
添加购物车成功后前端的页面如下;
redis中的购物车数量如下:
===========================================================================
对上面的添加购物车进行升级(增加用户未登录也能添加购物车的功能)
如果用户未登录,则购物车数据保存在用户的cookie中(用的浏览器中)
把用户的购物车数据以json字符串的方式保存在cookie中(cookie只能保存字符串) “cart”: ‘{ “sku_1“:10, “sku_2”: 11 }’
如果用户登录,则购物车数据是保存在后端的redis中,用户在登录的时候,将cookie中的购物车数据与redis中的数据进行合并,合并后保存在redis中
json模块
将python的字典类型数据转换为json字符串的方法 json.dumps(字典数据) {‘a’:1} ----> '{'a':1}'
将json字符串转换为python的字典类型数据的方法 json.loads(json字符串) '{'a':1}' ---> {'a':1}
业务逻辑的分析:
1 如果用户未登录,则将数据保存到cookie中
2 先获取用户的cookie中的购物车数据
3 取 出原来存储在浏览器中的cookie,把原来的转成字典
4 判断cookies是否包含传来的商品shu_id如果有则求和,没有则增加
5 把最新的商品数量设置到字典中
6 统计购物车中的商品总数
7 构建response对象
8 设置最新的cookie信息
添加用户未登录实现添加购物车的视图函数
用户未登录主要的代码
cart_json = request.COOKIES.get("cart") # 取原来存储在浏览器中的cookie if cart_json is not None: cart=json.loads(cart_json) # 把原来的转成字典 else: cart={} # 判断cookies是否包含传来的商品shu_id如果有则求和,没有则增加 if sku_id in cart: # 判断传过来的商品id是在以前的cookies中有,有则叠加 origin_count= cart[sku_id] count += origin_count # 把最新的商品数量设置到字典中 cart[sku_id]=count new_cart_json = json.dumps(cart) # 统计购物车中的商品总数 cart_num = 0 for val in cart.values(): cart_num += val response = JsonResponse({"code": 0, "message": "添加购物车成功", "cart_num": cart_num}) # 设置最新的cookie信息 response.set_cookie('cart',new_cart_json) return response
完整的代码:
class AddCartView(View): """添加购物车""" def post(self, request): # 判断用户是否登录 # if not request.user.is_authenticated(): # # 表示用户未登录 # return JsonResponse({"code": 1, "message": "用户未登录"}) # sku_id 商品id # count 商品数量 # 接受参数 sku_id = request.POST.get("sku_id") count = request.POST.get("count") # 校验参数 if not all([sku_id, count]): return JsonResponse({"code": 2, "message": "参数不完整"}) # 判断商品存在与否 try: sku = GoodsSKU.objects.get(id=sku_id) except GoodsSKU.DoesNotExist: # 表示商品不存在 return JsonResponse({"code": 3, "message": "商品不存在"}) # 判断用户请求的count是不是整数 try: count = int(count) except Exception: # 数量不是整数 return JsonResponse({"code": 4, "message": "参数错误"}) # 判断数量有没有超过库存 if count > sku.stock: return JsonResponse({"code": 5, "message": "库存不足"}) if request.user.is_authenticated(): # 业务逻辑处理,将数据保存到redis中 # {"sku_1": 10, "sku_2": 20} redis_conn = get_redis_connection("default") # 先从redis中尝试获取用户原有购物车中相同商品的信息 user_id = request.user.id origin_count = redis_conn.hget("cart_%s" % user_id, sku_id) # 如果redis中不存在,则直接将数据保存到redis的购物车中 # 如果redis中原本包含了这个商品的数量信息, 进行数量累加,在保存到redis中 if origin_count is not None: count += int(origin_count) # 在把新的购物信息设置会 redis中 redis_conn.hset("cart_%s" % user_id, sku_id, count) cart_num = 0 # 取出所有的购物车的数量返回给前端 cart =redis_conn.hgetall('cart_%s' %user_id) for val in cart.values(): cart_num +=int(val) # 通过返回json数据,告知前端处理的结果 return JsonResponse({"code": 0, "message": "添加购物车成功",'cart_num':cart_num}) else: # 如果用户未登录,则将数据保存到cookie中 # 先获取用户的cookie中的购物车数据 cart_json = request.COOKIES.get("cart") # 取原来存储在浏览器中的cookie if cart_json is not None: cart=json.loads(cart_json) # 把原来的转成字典 else: cart={} # 判断cookies是否包含传来的商品shu_id如果有则求和,没有则增加 if sku_id in cart: # 判断传过来的商品id是在以前的cookies中有,有则叠加 origin_count= cart[sku_id] count += origin_count # 把最新的商品数量设置到字典中 cart[sku_id]=count new_cart_json = json.dumps(cart) # 统计购物车中的商品总数 cart_num = 0 for val in cart.values(): cart_num += val response = JsonResponse({"code": 0, "message": "添加购物车成功", "cart_num": cart_num}) # 设置最新的cookie信息 response.set_cookie('cart',new_cart_json) return response