Django REST API与Axios POST请求失效问题求助
问题排查与解决:React+Django REST Framework数据提交异常
项目背景
开发简易API实现用户输入内容存入数据库,采用React+Django REST Framework技术栈,React通过npm run build打包后嵌入Django项目,项目结构如下:
- mysite(根目录)
- frontend(React项目)
- main(Django应用)
- mysite(Django配置目录)
- db.sqlite3
- manage.py
相关代码
App.js(React前端)
const [name,setName] = useState('') const handleChange = (e) => { setName(e.target.value) } function handleClick(e) { axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" axios.post('http://127.0.0.1:8000/post/', { headers: { "Content-Type": "application/x-www-form-urlencoded", 'X-CSRFToken': 'csrftoken' }, data:{ title: name, name: name } }) } return ( <> <form> <input type='text' value={name} onChange={handleChange} /> <button onClick={handleClick}>OK</button> </form> </> );
views.py(Django后端)
@api_view(['POST']) def home2(request): serializer = ItemSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response()
urls.py(Django路由)
from django.urls import path from . import views urlpatterns = [ path('api/',views.home,name='home'), path('post/',views.home2,name='home2'), path('a/',views.home3,name='home3') ]
settings.py(Django配置)
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'main', 'corsheaders' ] CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True
报错信息
- 前端控制台报错:
manifest.json:1 GET http://127.0.0.1:8000/manifest.json 404 (Not Found) manifest.json:1 Manifest: Line: 1, column: 1, Syntax error. - Django后端日志异常:
曾出现过Method Not Allowed: /post/ "POST /post/ HTTP/1.1" 400 5588"POST /post/ HTTP/1.1" 200 0的日志,但数据未存入数据库。
解决方案
1. 阻止表单默认提交行为
按钮位于<form>标签内,点击会触发浏览器默认表单提交(GET请求),与axios的POST请求冲突,需在点击事件中阻止默认行为:
function handleClick(e) { e.preventDefault(); // 添加此行代码 // 其余代码不变 }
2. 修正Axios请求参数格式
Axios的post方法参数结构错误,正确格式为axios.post(url, data, config),原代码将headers和data放在同一对象中,导致后端无法解析数据:
function handleClick(e) { e.preventDefault(); axios.defaults.xsrfCookieName = 'csrftoken'; axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"; // 调整参数结构 axios.post('http://127.0.0.1:8000/post/', { title: name, name: name }, // 第二参数为请求数据 { // 第三参数为配置项,包含headers headers: { "Content-Type": "application/json", // DRF默认适配JSON格式 } } ) .then(res => console.log('提交成功', res)) .catch(err => console.error('提交失败', err)); }
若坚持使用
application/x-www-form-urlencoded,需用qs.stringify()处理数据,但JSON格式更适配DRF默认配置。
3. 正确获取CSRF Token
硬写'X-CSRFToken': 'csrftoken'无效,需从Cookie中读取真实Token,可通过原生JS实现:
// 原生JS获取Cookie中的csrftoken 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; } // 在handleClick中使用 const csrftoken = getCookie('csrftoken'); axios.post('http://127.0.0.1:8000/post/', { title: name, name: name }, { headers: { "Content-Type": "application/json", 'X-CSRFToken': csrftoken } } )
4. 完善后端视图逻辑
当前视图未处理序列化失败场景,也未返回有效响应,需补充错误信息和状态码:
from rest_framework import status @api_view(['POST']) def home2(request): serializer = ItemSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) # 序列化失败时返回错误信息与400状态码 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
5. 解决manifest.json 404问题
React打包后的manifest.json位于frontend/build目录,需配置Django静态文件以正确访问:
- 在Django根目录
settings.py中添加:STATICFILES_DIRS = [ BASE_DIR / 'frontend/build/static', ] STATIC_ROOT = BASE_DIR / 'static' # 配置模板目录,让Django加载React打包后的index.html TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'frontend/build'], 'APP_DIRS': True, # 其余配置不变 }, ] - 执行
python manage.py collectstatic将React静态文件收集到Django静态目录。 - 若不需要manifest.json,可在React项目的
public/index.html中移除相关引用,或复制manifest.json到Django的static目录。
内容的提问来源于stack exchange,提问作者Django
相关产品推荐
相关产品推荐

