7 - 用户购物车模块
前端的页面如下:
前端的页面分析:
要实现添加购物车的功能,前端要向后端传送的数据有商品的id和添加的数量,并且后端规定以post的方式发送给后端.
后端视图函数的业务逻辑
1 判断用户是否登陆,没登陆返回用户未登录
2 接受前端传来的参数
3 对参数进行校验,判断是否有空的参数,有为空的参数返回参数不完整
4 对传过来的商品id进行数据库查询,看数据库中是否有这个商品存在,没有返回商品不存在
5 对参数添加购物车的数量的类型判断,如果不是整数,返回参数错误
6判断是否超过库存的数量,返回超过库存不足
7业务逻辑处理,将购物车数据保存到redis中
如果redis中不存在,则直接将数据保存到redis的购物车中
如果redis中原本包含了这个商品的数量信息, 进行数量累加,在保存到redis中通过返回json数据,告知前端处理的结果
8 将最新的购物车信息设置到redis中
=======================================================
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") });
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信息
用户未登录主要的代码
完整的代码:
点击添加购物车后用户的cookie信息:
========================================
在goods模块中写购物车模块的基类,让用到显示购物车数量的模块都去继承这个基类,
显示购物车的数量可以直接调用 cart_num = self.get_cart_num(request)
基类
各个类调用如下:
主页未登录也能通过cookie显示购物车的数量
前端显示的页面如下图所示:
根据前端页面后端要接受的参数如商品的sku_id和商品的数量,和用户的信息
后端视图函数的业务逻辑如下:
1 获取数据
2 如果用户未登录,从cookie中获取数据
3 如果用户已登陆, 从redis中获取数据
4 处理模板
业务逻辑
后端根据购物车的数据,通过查询数据库挨个遍历要给前端传送的数据有每个商品的对象(商品sku里面有图片,name,单位,价格,)商品的数量可以通过从redis或cookie中获取,把它当成一个商品的属性添加到商品的对象中,
小计可以通过商品的价格和商品的数量想乘后的结果添加到对象的属性中,最后总共有多少商品和价格可以选择两个变量在每次遍历商品的时候叠加操作。
查询购物车信息的视图函数(CartInfoView)代码如下
配置url的路径:
url(r"^$", views.CartInfoView.as_view(), name="info"),
前端的渲染效果如下:
在用户登陆成功后业务逻辑处理如下:
1 在用户登陆成功后先获取浏览器中购物车cookie的数据
2 在获取redis中购物车的数据
3 把浏览器中的cookie 同步到redis中
4 在redis中设置最新的购物车数据
5 清除浏览器中的cookie数据
在用户应用下登陆的视图函数中添加和修改如下的代码:
# 获取redis中购物车的数据
redis_con=get_redis_connection('default')
redis_cart=redis_con.hgetall('cart_%s' % user.id)
redis_cart.update(cart_cookie)
redis_con.hmset('cart_%s' %user.id,redis_cart)
# 判断页面的url中是否有next参数如果有,返回到原来的路径
next = request.GET.get('next')
if next:
response=redirect(next)
else:
# 登录成功,跳转到主页
response=redirect(reverse("goods:index"))
# 清楚浏览器中的cookie数据
response.delete_cookie('cart')
return response
登陆完整的视图函数代码如下:
用户登陆成功后浏览器中的cookie被清除了,页面的效果如下:
业务逻辑处理如下
1 分别取出在浏览器和数据库中的购物车数据后,
2 遍历cookie中的购物车信息通过cookie中的键判断商品在不在redis中在的话叠加,不在的话添加进去
注意的点
sku_id 从cookie取出时str类型,count是整形,redis中的sku_id和count都是是bytes类型,
1 那cookie中的sku_id在redis中查询要转换成bytes类型
2 把redis中的count和浏览器中cookie中的count想加要把redis中的count转换成int()
for sku_id,count in cart_cookie.items():
# sku_id 从cookie取出时str类型,redis中是bytes类型
sku_id=sku_id.encode()
if sku_id in redis_cart:
origin_count = redis_cart[sku_id]
count += int(origin_count)
redis_cart[sku_id]=count
redis_con.hmset('cart_%s' %user.id,redis_cart)
完整的代码如下:
效果如下:
1 用户登陆后查看购物车中草莓的数量为6:
2 用退出后添加一个草莓到购物车:
3 用户登陆后查看合并后想加的数据:
用户操作的前端页面如下所示:
前端页面分析:
当用户通过增加和减少的按钮或者直接在input框里面修改数值时,会通过ajax中的post请求的方式发送修改后的商品sku_id和数量交给后端进行判断
前端需要通过ajax给后端传送的数据有sku_id和商品的数量count
后端的业务逻辑处理如下:
1 接受前端通过post传送的数据(sku_id,count)
2 参数校验
判断商品是否存在
count是否是整数
判断库存是否充足
3 业务处理,保存数据
如果用户已登录保存在redis中
如果用户未登录保存在cookie中
4 返回json的响应数据
修改的视图处理如下:
当用户点击删除的操作后,购物车中的数据会移除,需要给前端传送的参数只有一个(商品的sku_id)
后端视图函数的业务逻辑处理如下:
1 获取参数
2 参数校验
3 业务处理删除购物车数据
4 返回处理的结果给前端
删除的视图处理函数如下:
总共有4件商品
当用户点击删除时
前端的代码如下: