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

Django-React框架图片上传返回403错误求助

问题分析与解决

1. 装饰器顺序错误导致@csrf_exempt失效

你当前将@api_view(['POST'])放在@csrf_exempt上方,DRF的api_view装饰器会优先处理请求,内部默认启用CSRF校验,导致@csrf_exempt无法生效。正确的装饰器顺序需将@csrf_exempt放在@api_view之前:

@csrf_exempt
@api_view(['POST'])
def upload_images(request, format=None):
    # 你的视图逻辑

不过更推荐的方式是保留CSRF校验,在React请求中正确携带Token,安全性更高。

2. React端正确携带CSRF Token的方法

Django会在用户访问页面时设置csrftoken Cookie,你可以在React中读取该Cookie,然后在上传请求的请求头中添加X-CSRFToken字段:

示例代码(React):

// 可使用js-cookie库简化Cookie读取,或自行实现读取逻辑
import Cookies from 'js-cookie';

const uploadImages = async (formData) => {
  const csrfToken = Cookies.get('csrftoken');
  try {
    const response = await fetch('/upload/', {
      method: 'POST',
      headers: {
        'X-CSRFToken': csrfToken,
        // 注意:上传文件时不要手动设置Content-Type,浏览器会自动处理multipart/form-data格式
      },
      body: formData,
    });
    // 处理响应逻辑
  } catch (error) {
    console.error(error);
  }
};

若不想依赖第三方库,可自行编写Cookie读取函数:

function getCookie(name) {
  let cookieValue = null;
  if (document.cookie && document.cookie !== '') {
    const cookies = document.cookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
      const cookie = cookies[i].trim();
      if (cookie.substring(0, name.length + 1) === (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}

3. 视图逻辑中的其他潜在错误

除CSRF问题外,你的视图还有两处需修正:

  • 模型字段为image_url,但你在Image.objects.create(image=images)中使用了不存在的image字段,需改为Image.objects.create(image_url=images)。
  • 你已通过serializer.save()创建实例,后续重复调用Image.objects.create会生成重复记录,需删除其中一处。

修正后的视图代码:

# 若采用React携带Token的方式,可移除@csrf_exempt装饰器
@csrf_exempt
@api_view(['POST'])
def upload_images(request, format=None):
    if request.method == 'POST':
        # 注意:many=True适用于批量上传,若前端仅传单个文件需移除该参数
        serializer = ImageSerializer(data=request.data, many=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

后台手动上传正常的原因

Django Admin内部已自动处理CSRF Token的携带逻辑,因此从Admin面板上传不会触发CSRF错误。

内容的提问来源于stack exchange,提问作者Jorge Rodríguez Peña

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 13:45:32