修改购物车数据
1. 后端接口设计
请求方式 : PUT /cart/
请求参数: JSON 或 表单
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
sku_id | int | 是 | 商品sku id |
count | int | 是 | 数量 |
selected | bool | 否 | 是否勾选,默认勾选 |
返回数据: JSON
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
sku_id | int | 是 | 商品sku id |
count | int | 是 | 数量 |
selected | bool | 是 | 是否勾选,默认勾选 |
2. 后端实现
在carts/views.py中修改视图,添加put方法
class CartView(APIView):
...
def put(self, request):
"""
购物车记录更新:
"""
# 1. 获取参数并进行校验(sku_id, count, selected)
serializer = CartSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
sku_id = serializer.validated_data['sku_id']
count = serializer.validated_data['count']
selected = serializer.validated_data['selected']
# 2. 获取user
try:
# 获取user时会执行使用认证机制进行认证,因为客户端传递了jwt 数据
# 如果认证失败,这句代码会报错
user = request.user
except Exception:
user = None
# 3. 更新购物车记录
if user is not None and user.is_authenticated:
# 3.1 如果用户已登录,更新redis中购物车记录
redis_conn = get_redis_connection('cart')
pl = redis_conn.pipeline()
# 设置用户购物车中商品的id和对应数量count hash
cart_key = 'cart_%s' % user.id
# hset(key, field, value): 设置hash中某个属性值
pl.hset(cart_key, sku_id, count)
# 设置用户购物车中商品的勾选状态 set
cart_selected_key = 'cart_selected_%s' % user.id
if selected:
# 勾选
# sadd(key, *values): 向set中添加元素
pl.sadd(cart_selected_key, sku_id)
else:
# 不勾选
# srem(name, *values): 从set中移除元素,如果元素不存在,直接忽略
pl.srem(cart_selected_key, sku_id)
pl.execute()
# 返回应答
return Response(serializer.data)
else:
response = Response(serializer.data)
# 3.2 如果用户未登录,更新cookie中购物车记录
cookie_cart = request.COOKIES.get('cart') # None
if cookie_cart is None:
return response
# 解析购物车中数据
cart_dict = pickle.loads(base64.b64decode(cookie_cart)) # {}
if not cart_dict:
return response
# 设置用户购物车商品数量count和勾选状态
cart_dict[sku_id] = {
'count': count,
'selected': selected
}
# 4. 返回应答
# 处理
cookie_data = base64.b64encode(pickle.dumps(cart_dict)).decode() # str
# 设置购物车cookie信息
response.set_cookie('cart', cookie_data, expires=constants.CART_COOKIE_EXPIRES)
return response
3. 前端实现
在cart.js中添加
on_input: function(index){
var val = parseInt(this.cart[index].count);
if (isNaN(val) || val <= 0) {
this.cart[index].count = this.origin_input;
} else {
// 更新购物车数据
axios.put(this.host+'/cart/', {
sku_id: this.cart[index].id,
count: val,
selected: this.cart[index].selected
}, {
headers:{
'Authorization': 'JWT ' + this.token
},
responseType: 'json',
withCredentials: true
})
.then(response => {
this.cart[index].count = response.data.count;
})
.catch(error => {
if ('non_field_errors' in error.response.data) {
alert(error.response.data.non_field_errors[0]);
} else {
alert('修改购物车失败');
}
console.log(error.response.data);
this.cart[index].count = this.origin_input;
})
}
},
// 更新购物车数据
update_count: function(index, count){
axios.put(this.host+'/cart/', {
sku_id: this.cart[index].id,
count,
selected: this.cart[index].selected
}, {
headers:{
'Authorization': 'JWT ' + this.token
},
responseType: 'json',
withCredentials: true
})
.then(response => {
this.cart[index].count = response.data.count;
})
.catch(error => {
if ('non_field_errors' in error.response.data) {
alert(error.response.data.non_field_errors[0]);
} else {
alert('修改购物车失败');
}
console.log(error.response.data);
})
},
// 更新购物车数据
update_selected: function(index) {
axios.put(this.host+'/cart/', {
sku_id: this.cart[index].id,
count: this.cart[index].count,
selected: this.cart[index].selected
}, {
headers: {
'Authorization': 'JWT ' + this.token
},
responseType: 'json',
withCredentials: true
})
.then(response => {
this.cart[index].selected = response.data.selected;
})
.catch(error => {
if ('non_field_errors' in error.response.data) {
alert(error.response.data.non_field_errors[0]);
} else {
alert('修改购物车失败');
}
console.log(error.response.data);
})
}