Django应用request.POST取POST参数返回None及404问题排查
代码里一共有4个核心问题,按下面改就能正常运行:
第一个问题:DOM元素ID重复
你在{% for product in product_list %}循环里,给所有商品的名称隐藏域、数量输入框、加购按钮都用了相同ID,HTML要求ID全局唯一,getElementById永远只会匹配页面第一个元素,后面的商品既绑不上事件,也拿不到正确值。而且你套的空<form>标签完全没用(你是用axios发异步请求,不是原生表单提交),直接删掉即可。
模板部分对应代码替换为:{% for product in product_list %} <li> <div class="container product-card" data-product-id="{{ product.id }}"> <img src="/media/{{product.product_image}}"> <div>{{ product.name }}</div> <div>{{ product.category }}</div> <div>{{ product.price }}</div> <div>{{ product.description }}</div> <input type="hidden" value="{{ product.name }}" class="prod-name"> <label>Quantity</label> <div class="input-group text-center mb-3" style="width:130px;"> <button class="input-group-text decrement-btn">-</button> <input type="text" name="quantity" class="form-control qty-input text-center" value="1"> <button class="input-group-text increment-btn">+</button> </div> <button class="btn btn-danger addToCartBtn">Add to cart</button> </div> </li> {% endfor %}这里顺便把原来
ul下直接套div的不规范结构改了,ul的直接子元素必须是li,不然会有渲染异常。第二个问题:后端无法获取POST参数
Axios默认发送的POST请求体是application/json格式,Django的request.POST只解析application/x-www-form-urlencoded类型的表单数据,所以你拿值永远是None。把addToCart视图改成解析JSON请求体即可,异步接口不要返回重定向,直接返回JSON响应:def addToCart(request): if request.method == 'POST': data = json.loads(request.body) prod_name = data.get('Product Name') prod_quantity = data.get('Product Quantity') print(prod_name, prod_quantity) # 后续在这里写购物车数据存入数据库/会话的逻辑 return JsonResponse({'code': 0, 'msg': '加购成功'}) return JsonResponse({'code': -1, 'msg': '请求方式错误'}, status=405)你之前报404就是因为返回了相对路径的
HttpResponseRedirect('get_smart/'),请求路径是/ecomm/addToCart/时,相对路径会拼接成/ecomm/addToCart/get_smart/,这个路径没有在路由里注册,自然报404。第三个问题:JS事件绑定逻辑错误
原来的JS只给第一个加购按钮绑了事件,也没给数量加减按钮写逻辑,替换为以下代码即可:axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" // 绑定所有加购按钮事件 document.querySelectorAll(".addToCartBtn").forEach(btn => { btn.addEventListener("click", function(e){ e.preventDefault(); // 定位当前点击按钮所属的商品卡片 const card = this.closest(".product-card") const productName = card.querySelector(".prod-name").value const quantity = Number(card.querySelector(".qty-input").value) axios.post('/ecomm/addToCart/', { 'Product Name': productName, 'Product Quantity': quantity }).then(res => { if(res.data.code === 0) alert(res.data.msg) }) }) }) // 绑定数量加减按钮逻辑 document.querySelectorAll(".decrement-btn").forEach(btn => { btn.addEventListener("click", function(){ const input = this.nextElementSibling const currVal = Number(input.value) if(currVal > 1) input.value = currVal - 1 }) }) document.querySelectorAll(".increment-btn").forEach(btn => { btn.addEventListener("click", function(){ const input = this.previousElementSibling const currVal = Number(input.value) input.value = currVal + 1 }) })
改完之后加购功能就能正常获取参数、返回响应,不会再出现None和404的问题。
内容的提问来源于stack exchange,提问作者theritter

