React+DRF单页应用POST请求404问题排查求助
嘿,我一眼就从日志里看出问题所在了——URL末尾的斜杠不匹配导致了POST请求的404错误!
先看你的日志细节:
[20/Apr/2018 13:59:11] "GET /api/v1/update/ HTTP/1.1" 200 454
Not Found: /api/v1/update
[20/Apr/2018 13:59:11] "POST /api/v1/update HTTP/1.1" 404 2421
GET请求用的是/api/v1/update/(带末尾斜杠),后端能匹配到路由返回200;但POST请求用的是/api/v1/update(不带斜杠),后端找不到对应的路由,所以直接返回404。这是Django/DRF路由系统的典型行为:Django默认要求URL末尾带斜杠(由APPEND_SLASH = True配置控制),GET请求会自动重定向到带斜杠的版本,但POST请求不会(因为重定向会丢失请求体),所以直接触发404。
解决方法有两种,推荐第一种:
方法1:修改前端POST请求的URL,加上末尾斜杠
这是最符合Django规范的做法,只需要在React代码里把请求地址补全末尾的斜杠即可。比如用fetch的例子:
fetch('/api/v1/update/', { method: 'POST', headers: { 'Content-Type': 'application/json', // 别忘了带上CSRF令牌(如果你的DRF开启了CSRF保护) 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value }, body: JSON.stringify(yourFormData) })
如果用Axios:
axios.post('/api/v1/update/', yourFormData, { headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value } })
方法2:调整后端路由,兼容不带斜杠的请求
如果你不想修改前端代码,可以在Django的urls.py里调整路由规则,让它同时匹配带斜杠和不带斜杠的URL:
from django.urls import re_path from .views import TaskFormView urlpatterns = [ # 用正则表达式匹配可选的末尾斜杠 re_path(r'^api/v1/update/?$', TaskFormView.as_view(), name='task-form'), ]
不过这种方式会打破Django的URL规范,可能引发后续其他路由问题,所以优先推荐方法1。
最后再快速确认下:你的TaskFormView类确实正确实现了post方法对吧?比如:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class TaskFormView(APIView): def get(self, request, format=None): # 你的GET逻辑 return Response({"message": "GET请求正常"}) def post(self, request, format=None): # 确保这里有正确的POST处理逻辑 # 比如序列化、保存数据等 return Response({"message": "POST请求成功"}, status=status.HTTP_201_CREATED)
如果post方法拼写错误(比如写成posts)会返回405,但你的情况是404,所以核心问题还是URL的斜杠匹配。
内容的提问来源于stack exchange,提问作者Pavel Rodionov

