DRF+AJAX删除购物车商品时提示GET方法不允许的问题
问题解决:购物车删除按钮跳转API并提示Method 'GET' not allowed
核心问题分析
- 重复ID导致事件绑定失效:动态生成的删除按钮都使用同一个
id="deleteCartProduct",jQuery的ID选择器仅会绑定第一个匹配元素,后续按钮点击时会触发<a>标签的默认跳转行为(发送GET请求),但API仅接受DELETE方法,因此报错。 - 请求参数传错:AJAX删除请求中传递的是用户ID,而API需要的是待删除的商品ID,导致请求目标错误。
- 视图权限判断逻辑错误:
cart_instance是QuerySet对象,无法直接访问buyer_id属性,会引发AttributeError。
修复步骤及代码修改
1. 替换重复ID为类选择器,绑定事件委托
将删除按钮的id="deleteCartProduct"改为class="deleteCartProduct",通过事件委托绑定点击事件,确保动态生成的元素也能触发AJAX请求:
修改displayCart函数中的按钮代码:
// 原代码 "<a class='btn btn-danger' id='deleteCartProduct' href="+base_url+"/cart/api/delete_cart_product/"+data.id+" role='button'>Delete</a>" // 修改后 "<a class='btn btn-danger deleteCartProduct' data-product-id='"+data.id+"' href='javascript:void(0)' role='button'>Delete</a>"
修改AJAX绑定代码:
// 原代码 $("#deleteCartProduct").click(function(event){...}) // 修改后,用事件委托绑定到父元素 $('#cartProductDisplay').on('click', '.deleteCartProduct', function(event){ event.preventDefault(); console.log('Delete Cart Product test') var base_url = window.location.origin; // 从按钮的data属性获取商品ID var productId = $(this).data('product-id'); $.ajax({ method: 'DELETE', beforeSend: function(xhr, settings) { xhr.setRequestHeader("X-CSRFToken", csrftoken); }, url : base_url + '/cart/api/delete_cart_product/'+productId+ '/', success: function(response) { // 删除成功后移除对应卡片,无需跳转页面 $(this).closest('.card').remove(); console.log('cart product deleted!') console.log(response); }.bind(this), // 绑定this指向当前点击的按钮 error: function() { console.log('sum ting wong delete cart product'); } }); });
2. 修复视图中的权限判断错误
修改delete_cart_product方法的权限校验逻辑:
# 原代码 if cart_instance.buyer_id != request.user.id: return Response( {"res": "You are not the owner of the cart!"}, status = status.HTTP_400_BAD_REQUEST ) # 修改后 if not cartProduct_instance: return Response( {"res": "Cart product not found!"}, status=status.HTTP_404_NOT_FOUND ) if cartProduct_instance.buyer_id != request.user.id: return Response( {"res": "You are not the owner of this cart item!"}, status=status.HTTP_403_FORBIDDEN )
3. 优化购物车查询逻辑(可选)
get_cart_products方法当前返回所有用户的购物车数据,应改为仅返回当前登录用户的:
def get_cart_products(self, request, *args, **kwargs): # 仅查询当前用户的购物车 cartProduct = Cart.objects.filter(buyer=request.user) if cartProduct.exists(): cartSerializer = CartSerializer(cartProduct, many=True) return Response(cartSerializer.data, status=status.HTTP_200_OK) else: return Response({"res": "Cart is empty"}, status=status.HTTP_200_OK)
其他注意事项
- 确保页面中正确定义
csrftoken变量,否则AJAX请求会被Django的CSRF保护拦截:var csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; - 动态生成元素时,避免使用重复ID,优先使用类选择器或自定义data属性传递参数。
内容的提问来源于stack exchange,提问作者monke_monk
相关产品推荐
相关产品推荐

