Django中使用JS发起POST请求报CSRF token缺失如何解决
Django无刷新加购功能修复方案
核心报错原因
当前CSRF 403报错的直接原因是AJAX传参格式错误:你设置了请求头Content-Type为application/x-www-form-urlencoded,但send()方法直接传入原生JS对象时,浏览器不会自动将对象转换为该格式要求的键值对字符串,最终请求体里没有携带csrfmiddlewaretoken字段,Django的CSRF中间件校验直接拦截请求。
除此之外你的代码还有3个会导致功能异常的隐藏问题,按顺序修复即可。
分步修复代码
1. 修复路由配置
你当前路由有两个错误:一是路径开头多写了斜杠会导致路径匹配异常,二是直接将类视图的post方法绑定到路由会导致参数错位(request会被传入self参数位置,后续调用类属性、方法会直接报错)。
修改urls.py:
app_name = 'basket' urlpatterns = [ path('', views.BasketView.as_view(), name='summary'), # 去掉路径开头的斜杠,单独写加购视图走as_view()分发 path('add', views.BasketAddView.as_view(), name='basket_add'), ]
2. 修复视图逻辑
原视图直接返回字符串不符合Django响应要求,必须返回HttpResponse或其子类对象,单独新增加购视图:
from django.http import JsonResponse from django.views import View from django.views.generic import ListView from .models import Category # 原购物车页面视图 class BasketView(ListView): template_name = 'basket/basket.html' model = Category # 新增加购接口视图 class BasketAddView(View): def post(self, request, *args, **kwargs): # 打印POST数据时建议转成普通字典,打印结果更直观 print("接收到的POST数据:", dict(request.POST)) # 后续这里写加购逻辑:校验商品是否存在、库存是否充足、操作购物车数据 return JsonResponse({"code": 0, "msg": "添加成功"})
3. 修复AJAX请求代码
用URLSearchParams将参数转为urlencoded格式,保证CSRF token能正常被后端接收,修改JS部分:
function send_productId(id){ var request = new XMLHttpRequest(); request.open('POST', '{% url 'basket:basket_add' %}', true); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); // 用URLSearchParams包装参数,自动转成符合格式的请求体 const data = new URLSearchParams({ id: id, csrfmiddlewaretoken: '{{ csrf_token }}' }); request.send(data); // 加请求回调方便调试 request.onload = function() { if (request.status === 200) { const res = JSON.parse(request.responseText); console.log("请求成功,返回结果:", res); // 这里可以写后续交互:更新购物车角标数字、弹出加购成功提示 } else { console.log("请求失败,状态码:", request.status); } } }; function basket_add(obj){ // 建议后续把商品id存在data-product-id自定义属性上,不要占用原生id属性 send_productId(obj.id); };
实现优化建议
- 不要把商品id直接存在按钮的
id属性上,改用自定义属性存储:<button data-product-id="{{ item.id }}" onclick="basket_add(this)"></button>,取值时用obj.dataset.productId,避免和页面其他元素id冲突 - 后端加购逻辑必须做合法性校验:判断传入的商品id是否存在、对应商品是否上架、库存是否充足,不能直接信任前端传参,避免恶意请求篡改购物车数据
- 加购请求完成后必须给用户明确反馈,比如弹出“加购成功”提示、更新页面右上角购物车的商品数量角标,不然用户点击按钮后无感知
- 如果项目已经引入jQuery,直接用
$.ajax/$.post发送请求即可,不用手写原生XMLHttpRequest,jQuery会自动处理参数格式转换,也可以全局配置CSRF token,不用每次请求手动携带
内容的提问来源于stack exchange,提问作者4SadMemeXD
相关产品推荐
相关产品推荐

