使用Django+React开发购物车时加入购物车接口报500错误如何解决
报错的核心原因是 Django没有识别到当前登录的用户,request.user返回的是匿名用户对象,无法赋值给要求必须是正式User实例的order_product.user字段,按以下步骤修复即可:
1. 后端接口添加登录权限校验
你当前视图的permission_classes = []表示允许所有用户(包括未登录的匿名用户)访问该接口,但创建购物车关联数据必须绑定已登录用户,所以首先修改视图权限配置:
# 先导入权限类 from rest_framework.permissions import IsAuthenticated class add_to_cart_view(APIView): # 替换为空权限的配置,仅允许已登录用户访问 permission_classes = [IsAuthenticated] # 剩下的原有代码不变
修改后未登录用户调用该接口会直接返回401错误,不会走到后续创建数据的逻辑触发500报错。
2. 后端配置跨域凭证允许
因为React前端和Django后端端口不同属于跨域请求,默认Django不会接收跨域请求携带的身份凭证(sessionid),需要配置跨域规则:
首先安装django-cors-headers依赖:pip install django-cors-headers
然后修改settings.py配置:
INSTALLED_APPS = [ # ... 其他原有应用 'corsheaders', ] MIDDLEWARE = [ # 放在最顶部,优先执行跨域校验 'corsheaders.middleware.CorsMiddleware', # ... 其他原有中间件 'django.middleware.common.CommonMiddleware', ] # 允许前端地址跨域访问,替换成你实际的React前端地址 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ] # 允许跨域请求携带凭证 CORS_ALLOW_CREDENTIALS = True
3. 前端请求配置携带身份凭证
默认axios不会在跨域请求中携带cookie,需要主动开启withCredentials配置:
const handleAddToCartURL = async (id) => { try { const res = await axios.post(`${AddToCartURL}/add-to-cart/`, {id}, { // 开启携带凭证 withCredentials: true }); setProduct(res.data); console.log(res.data) } catch (err) { // 建议添加错误处理,比如401时跳转到登录页 console.log(err) } };
你也可以全局配置axios的withCredentials属性,避免每个请求都单独配置:axios.defaults.withCredentials = true
4. 修复视图中隐藏的代码错误
你视图的else分支存在一处笔误,会导致后续创建订单时报错:
# 原有错误写法:add的参数是模型类,不是你创建的实例 order.products.add(order_product) # 修改为你刚创建的order_product实例 order.products.add(requested_product)
完成以上修改后,确保用户在前端已经完成登录,再调用加入购物车接口即可正常运行。如果需要支持未登录用户使用购物车,可以将order_product模型的user字段设置为允许为空,同时用session存储匿名用户的购物车数据,用户登录后再合并到账号下。
内容的提问来源于stack exchange,提问作者C-Bizz

