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

使用React+Axios向Django传图片时遭遇403 Forbidden错误求助

问题描述

我用React调用Django REST Framework API实现图片上传,提交时返回403 Forbidden错误,怀疑和CSRF Token有关,也可能是其他问题。作为新手,求正确代码帮忙解决。


原代码

Image.js

import React, { useState} from 'react';
    
axios.defaults.xsrfHeaderName = 'X-CSRFTOKEN';
axios.defaults.xsrfCookieName = 'csrftoken';
    
export default function Image() {
  const[images,setImages]=useState(null);
    
  function handleImages(e){
    setImages(e.target.files[0])
  }
  function handleSubmit(event){
    const formData= new FormData();
    formData.append('images',images)
    axios.post('http://127.0.0.1:8000/',formData,{
      headers:{ "Content-Type": "multipart/form-data" }}
    ).then((res)=>{
      console.log(res)
    })
  }
        
  return (
    <div>
      <input type="file" name="images"  accept="image/*"  onChange={handleImages}/>
      <button onClick={handleSubmit}>Upload</button>
    </div>
  )
}

views.py

from rest_framework.parsers import FileUploadParser
from rest_framework import viewsets
from .serializers import RentDetailsSerializer
from  firstapp.models import RentDetails
from rest_framework.parsers import MultiPartParser, FormParser

class RentDetailsViewSet(viewsets.ModelViewSet):
    serializer_class=RentDetailsSerializer
    queryset=RentDetails.objects.all();
   
    parser_classes = [MultiPartParser, FormParser]

serializers.py

from rest_framework import  serializers
from firstapp.models import RentDetails

class RentDetailsSerializer(serializers.ModelSerializer):
    images=serializers.ImageField(required=False)
    class Meta:
        model = RentDetails
        fields = ['floor_no','distance','location','area','no_of_rooms','price','property_type','images']

settings.py

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser'
    ]
}
# REST_FRAMEWORK = {
#     'DEFAULT_AUTHENTICATION_CLASSES': (
#         'rest_framework.authentication.TokenAuthentication',
#     )
# }
    
# CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_HEADERS = [
    "accept",
    "accept-encoding",
    "authorization",
    "content-type",
    "dnt",
    "origin",
    "user-agent",
    "x-csrftoken",
    "x-requested-with",
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

CORS_ORIGIN_WHITELIST = [
     'http://localhost:3000',
     'http://localhost:8000',
]
CSRF_COOKIE_NAME = "XSRF-TOKEN"
CORS_ALLOW_CREDENTIALS = True

问题分析与解决方案

403错误主要集中在CSRF验证、CORS配置、请求参数这几个方面,以下是针对性修改:

1. React端(Image.js)修改

  • 补全axios导入(原代码遗漏)
  • 开启withCredentials确保携带Cookie(含CSRF Token)
  • 不要手动设置Content-Type,axios会自动生成带boundary的正确请求头
  • 修正请求URL为ViewSet的实际路由(需和Django路由配置匹配)

修改后的Image.js:

import React, { useState} from 'react';
import axios from 'axios'; // 新增导入

// 配置axios与Django的CSRF参数匹配
axios.defaults.xsrfHeaderName = 'X-CSRFTOKEN';
axios.defaults.xsrfCookieName = 'XSRF-TOKEN'; // 和settings.py中CSRF_COOKIE_NAME一致
axios.defaults.withCredentials = true; // 强制携带Cookie

export default function Image() {
  const[images,setImages]=useState(null);
    
  function handleImages(e){
    setImages(e.target.files[0])
  }

  async function handleSubmit(event){
    event.preventDefault();
    if (!images) return; // 无图片时不提交

    const formData= new FormData();
    formData.append('images', images);

    try {
      // 替换为你的ViewSet实际路由
      const res = await axios.post('http://127.0.0.1:8000/api/rentdetails/', formData);
      console.log(res);
      alert('上传成功');
    } catch (err) {
      console.error('上传失败:', err.response);
      alert('上传失败,请检查控制台');
    }
  }
        
  return (
    <div>
      <input type="file" name="images" accept="image/*" onChange={handleImages}/>
      <button onClick={handleSubmit}>Upload</button>
    </div>
  )
}

2. Django端(settings.py)修改

  • 升级CORS配置为新版本的CORS_ALLOWED_ORIGINS(替代过时的CORS_ORIGIN_WHITELIST)
  • 添加CSRF_TRUSTED_ORIGINS,信任前端域名以通过CSRF验证
  • 全局解析器添加文件上传支持的MultiPartParser

修改后的settings.py核心配置:

INSTALLED_APPS = [
    # ... 其他应用
    'rest_framework',
    'corsheaders', # 确保已安装并添加
    'firstapp',
]

MIDDLEWARE = [
    # ... 其他中间件
    'corsheaders.middleware.CorsMiddleware', # 必须放在CommonMiddleware之前
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware', # 确保启用CSRF中间件
]

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.MultiPartParser', # 新增文件上传解析器
        'rest_framework.parsers.FormParser',
    ]
}

# CORS配置
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
    "http://127.0.0.1:3000",
]

# CSRF信任域名
CSRF_TRUSTED_ORIGINS = [
    "http://localhost:3000",
    "http://127.0.0.1:3000",
]

CSRF_COOKIE_NAME = "XSRF-TOKEN"
CORS_ALLOW_CREDENTIALS = True

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

3. Django路由配置(urls.py)

确保ViewSet已正确注册,项目根urls.py示例:

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from firstapp.views import RentDetailsViewSet

router = DefaultRouter()
router.register(r'rentdetails', RentDetailsViewSet) # 注册视图集

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include(router.urls)), # API根路径
]

4. 额外检查项

  • 执行pip install django-cors-headers安装CORS插件(未安装的话)
  • 确保RentDetails模型的images字段为models.ImageField(upload_to='images/'),并配置好MEDIA_ROOT和MEDIA_URL
  • 开发环境保持DEBUG=True,生产环境需严格配置域名和HTTPS

内容的提问来源于stack exchange,提问作者jen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:20:31