使用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
相关产品推荐
相关产品推荐

