后端
紧接着添加功能后
#添加购物车视图
class Cartview(APIView):
#添加购物车
def post(self,request,goods_id):
user=request.META.get('USER') #获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code':400,
'msg':'用户未登录'
})
user_id=user['user_id']
r=redis.Redis(host='127.0.0.1',port=6379,password='shayebushi')
key='cart:'+str(user_id)
#存入数据库
#先判断商品是否存在
goods_info=Goods.objects.filter(id=goods_id).first()
if not goods_info:
return Response({
'code':400,
'msg':'商品不存在'
})
cart={ #前端vuex里的数据结构
'id': goods_id, # 购物车id
'productID': goods_id, # 商品id
'productName': goods_info.sku_name, # 商品名称
'productImg': goods_info.img, # 商品图片
'price': goods_info.selling_price, # 商品价格
'num': 1, # 加购的商品数量
'maxNum': goods_info.stock, # 商品限购数量
'check': False # 是否勾选
}
#当前商品是否已经存在购物车
is_exist=r.hexists(key,goods_id)
if is_exist:
#判断一下商品数量是非法已经超出库存量
goods_count=r.hget(key,goods_id)#当前商品加入购物车的数量 返回的是byte类型
goods_count_int=int(goods_count.decode())
if goods_count_int>=goods_info.stock:
return Response({
'code':400,
'msg':'购物车商品已达到上限'
})
#购物车数量加1
r.hincrby(key,goods_id,1)
cart['num']=goods_count_int+1
return Response({
'code':201,
'msg':'商品已经在购物车,购物车数量加一',
'cart':cart
})
else:
#把商品添加到购物车
r.hset(key,goods_id,str(1))
return Response({
'code':200,
'msg':'加入购物车成功',
'cart':cart
})
#修改数量
def put(self,request,goods_id):
user = request.META.get('USER') # 获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code': 400,
'msg': '用户未登录'
})
user_id = user['user_id'] #当前登录用户
num=request.data.get('num') #修改后的数量
#判断一下商品是否在当前用户的购物车
r=redis.Redis(host='127.0.0.1',port=6379,password='shayebushi')
key='cart:%s'%user_id
is_exists=r.hexists(key,goods_id) #判断某商品是否在购物车中
if not is_exists:
return Response({
'code':400,
'msg':'商品不在购物车中'
})
#判断一下商品是否存在
goods_info=Goods.objects.filter(id=goods_id).first()
if not goods_info:
return Response({
'code':400,
'msg':'商品不存在'
})
#判断一下是否超出了库存量
if int(num)>goods_info.stock:
return Response({
'code':400,
'msg':'超出库存量'
})
#修改数据库中的数据
r.hset(key,goods_id,num)
r.close()
#返回
return Response({
'code':200,
'msg':'购物车数量更新成功,当前数量%s'%num,
})
#删除购物车
def delete(self,request,goods_id):
user = request.META.get('USER') # 获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code': 400,
'msg': '用户未登录'
})
user_id = user['user_id']
r = redis.Redis(host='127.0.0.1', port=6379, password='shayebushi')
key='cart:%s'%user_id
select_key='cart_select:%s'%user_id
#从购物车删除
r.hdel(key,goods_id)
#从选中的商品中删除
r.srem(select_key,goods_id)
#返回
return Response({
'code':200,
'msg':'删除成功'
})
# 查看购物车
class Showcartview(APIView):
#获取查看购物车
def get(self,request):
user=request.META.get('USER') #获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code':400,
'msg':'用户未登录'
})
user_id=user['user_id']
#获取到redis里面存储的商品信息
r=redis.Redis(host='127.0.0.1',port=6379,password='shayebushi')
key = 'cart:' + str(user_id)
goods_list=r.hgetall(key)
goods_all=[]
for (k,v) in goods_list.items():
k=k.decode() #商品id
v=v.decode() #商品加购数量
goods_info=Goods.objects.filter(id=k).first()
if not goods_info: #如果商品不存在,跳过该商品
continue
select_key = 'cart_select:%s' % user_id
is_exists=r.sismember(select_key,k)
info={ #前端vuex里的数据结构
'id': k, # 购物车id
'productID': k, # 商品id
'productName': goods_info.sku_name, # 商品名称
'productImg': goods_info.img, # 商品图片
'price': goods_info.selling_price, # 商品价格
'num': int(v), # 加购的商品数量
'maxNum': goods_info.stock, # 商品限购数量
'check': is_exists # 是否勾选
}
goods_all.append(info)
return Response({
'code':200,
'msg':'商品获取成功',
'goods':goods_all
})
#购物车全选与全不选
def post(self,request):
user = request.META.get('USER') # 获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code': 400,
'msg': '用户未登录'
})
user_id = user['user_id']
check=request.data.get('check') #前台传过来的用户是否全选
r = redis.Redis(host='127.0.0.1', port=6379, password='shayebushi')
key='cart:%s'%user_id
select_key='cart_select:%s'%user_id
if check=='check':
#执行全选逻辑
#获取购物车所有商品id
goods_ids=r.hkeys(key)
goods_ids_int=[]
for i in goods_ids:
goods_ids_int.append(i.decode())
#把商品id全部添加到选中的集合里面
r.sadd(select_key,*goods_ids_int)
return Response({
'code':200,
'msg':'全选成功'
})
#走到这就执行全都不选逻辑
r.delete(select_key)
return Response({
'code': 201,
'msg': '取消全选成功'
})
#购物车单选
class Cartcheckview(APIView):
def post(self,request,goods_id):
user = request.META.get('USER') # 获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code': 400,
'msg': '用户未登录'
})
user_id = user['user_id']
#判断商品是否存在
goods_info=Goods.objects.filter(id=goods_id).first()
if not goods_info:
return Response({
'code':400,
'msg':'商品不存在'
})
#链接reids数据库
#判断商品是否存在购物车
r=redis.Redis(host='127.0.0.1',port=6379,password='shayebushi')
key='cart:%s'%user_id
is_exists=r.hexists(key,goods_id)
if not is_exists:
return Response({
'code':400,
'msg':'商品不在购物车'
})
#判断商品是否选中
select_key='cart_select:%s'%user_id
is_check=r.sismember(select_key,goods_id)
if is_check: #商品已经选中
#执行不选中
r.srem(select_key,goods_id)
return Response({
'code':201,
'msg':'取消选中成功'
})
#程序走到这一步,数模商品未选中
#执行选中
r.sadd(select_key,goods_id)
return Response({
'code': 200,
'msg': '选中成功'
})
配置路由
from django.urls import path
from goods import views
urlpatterns = [
path('cart/<int:goods_id>/',views.Cartview.as_view()), #购物车增删改
path('cart/check/<int:goods_id>/',views.Cartcheckview.as_view()), #购物车的选中与不选择
path('cart/',views.Showcartview.as_view()), #查看购物车,选中购物车
]
前端
找到对应的vue文件,对相关的功能函数进行修改
例如:ShoppingCart.vue
methods: {
...mapActions(["updateShoppingCart", "deleteShoppingCart", "checkAll"]),
// 修改商品数量时,触发
handleChange(currentValue, key, productID) {
console.log("@@修改商品数量了......")
// currentValue,当前商品的新数量
// key,商品{} 在shoppingChart数组中 的索引
// productID 当前商品的id
console.log("商品ID", productID, "数量为", currentValue, "在列表中索引为", key)
// 1.修改数量时,设置为 勾选状态
this.updateShoppingCart({key: key, prop: "check", val: true});
// 2.TODO django后端修改购物车数量
this.$axios.put('/goods/cart/'+productID+'/',{
'num':currentValue
},{
'headers':{
'token':localStorage.getItem('token')
}
}).then((result) => {
if (result.data.code==200){
// 更新vuex中的数据
this.updateShoppingCart({
'prop':'num',
'key':key,
'val':currentValue,
})
this.notifySucceed(result.data.msg)
}else{
this.notifyError(result.data.msg)
}
}).catch((err) => {
console.log(err)
});
},
// 单选
checkChange(val, key, productID) {
console.log("商品ID:", productID, "选中状态为:", val, "在列表中索引为", key)
// TODO django 后端设置数据单选
this.$axios.post('goods/cart/check/'+productID+'/',{},{
'headers':{
'token':localStorage.getItem('token')
}
}).then((result) => {
if (result.data.code==200){
this.updateShoppingCart({
'prop':'check',
'key':key,
'val':true
})
this.notifySucceed(result.data.msg)
}else if(result.data.code==201){
this.updateShoppingCart({
'prop':'check',
'key':key,
'val':false
})
this.notifySucceed(result.data.msg)
}else{
this.notifyError(result.data.msg)
}
}).catch((err) => {
console.log(err)
});
},
// 向后端请求删除购物车的 商品信息
deleteItem(e, productID) {
console.log("删除的商品ID:", productID)
// TODO 后端删除商品ID
this.$axios.delete('/goods/cart/'+productID+'/',{
'headers':{
'token':localStorage.getItem('token')
}
}).then((result) => {
if (result.data.code==200){
this.notifySucceed(result.data.msg)
this.deleteShoppingCart(productID)
}else{
this.notifyError(result.data.msg)
}
}).catch((err) => {
console.log(err)
});
}
},
computed: {
...mapGetters([
"getShoppingCart", //获取vuex中的购物车数组
"getCheckNum", //获取购物车中勾选的商品数量
"getTotalPrice",
"getNum", //计算属性,获取购物车中的商品总数
]),
isAllCheck: {
// 读的时候执行getter
get() {
return this.$store.getters.getIsAllCheck;
},
// 写的时候,执行setter
set(val) {
console.log("设置全选状态为", val)
// TODO 设置全选状态
var check='check'
if (!val){
check=''
}
this.$axios.post('/goods/cart/',{
'check':check,
},{
'headers':{
'token':localStorage.getItem('token')
}
}).then((result) => {
if (result.data.code==201){
this.notifySucceed(result.data.msg)
for (var j=0;j < this.getShoppingCart.length;j++){
this.updateShoppingCart({
'prop':'check',
'key':j,
'val':false,
})
}
}else if (result.data.code==200){
this.notifySucceed(result.data.msg)
for (var i=0;i < this.getShoppingCart.length;i++){
this.updateShoppingCart({
'prop':'check',
'key':i,
'val':true
})
}
}else{
this.notifyError(result.data.msg)
}
}).catch((err) => {
console.log(err)
});
}
}
}