You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 02:39:09