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

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

报错信息

  1. 前端控制台报错:
    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.
    
  2. 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静态文件以正确访问:

  1. 在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,
            # 其余配置不变
        },
    ]
    
  2. 执行python manage.py collectstatic将React静态文件收集到Django静态目录。
  3. 若不需要manifest.json,可在React项目的public/index.html中移除相关引用,或复制manifest.json到Django的static目录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:23:11