使用Django REST Framework POST数据时报404 Not Found如何解决?
解决Django REST Framework跨Docker主机POST请求404问题
问题描述
通过浏览器访问Django REST Framework的可浏览API时,/api/strategy/target/能正常显示对象列表及POST表单,且表单提交可成功创建数据;但使用Python requests库跨Docker主机发送POST请求时,服务器返回404 Not Found,日志记录显示请求路径未找到。服务器与客户端分别运行在不同Docker主机的容器中。
服务器端信息
控制台日志
django-1 | Not Found: /api/strategy/target/ django-1 | [26/Sep/2022 14:27:05] "POST /api/strategy/target/ HTTP/1.1" 404 23
项目URL配置(project/project/urls.py)
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path("api/strategy/", include("strategy.urls")), ]
应用URL配置(strategy/urls.py)
from django.urls import path, include from rest_framework import routers from strategy.api.views import TargetViewSet router = routers.DefaultRouter() router.register("target", TargetViewSet, basename="targets-list") urlpatterns = [ path('', include(router.urls)), ]
视图代码(strategy/views.py)
from rest_framework import viewsets from strategy.api.serializers import TargetSerializer from rest_framework.decorators import permission_classes from rest_framework.permissions import IsAdminUser # Create new model @permission_classes([IsAdminUser]) class TargetViewSet(viewsets.ModelViewSet): serializer_class = TargetSerializer queryset = Target.objects.all()
客户端请求代码
res = requests.post("http://1.2.3.4:8001/api/strategy/target/", data=data, headers={'Authorization': 'Bearer {0}'.format(token)} )
排查与解决方案
1. 确认URL斜杠一致性
Django默认开启APPEND_SLASH(默认值为True),浏览器访问时会自动补全URL末尾的斜杠并重定向,但requests不会自动处理该逻辑。可浏览API的表单提交会自动生成带斜杠的请求URL,但客户端代码若因拼写或其他原因发送了无斜杠的请求,会触发404。
- 检查客户端代码中URL末尾是否明确包含
/; - 确认Django项目
settings.py中APPEND_SLASH = True,确保服务器能自动处理无斜杠的URL重定向。
2. 验证跨Docker主机的网络连通性
- 确认服务器容器的8001端口已正确映射到宿主主机的8001端口,且宿主主机的防火墙、安全组已开放该端口的外部访问权限;
- 在客户端主机执行
curl http://1.2.3.4:8001/api/strategy/target/,验证是否能正常获取可浏览API页面,排除网络层面的连通问题。
3. 排查权限验证导致的隐性404
视图配置了IsAdminUser权限,若请求携带的token无效、过期,或对应的用户非管理员,DRF在部分场景下会返回404而非预期的403 Forbidden,以此隐藏敏感路由信息。
- 打印客户端响应内容
print(res.content),查看是否包含权限相关的提示信息; - 使用相同token在浏览器中提交可浏览API的POST表单,验证权限是否正常;
- 在服务器端添加日志,打印请求头中的token及用户验证结果,排查权限校验流程。
4. 检查请求数据格式
DRF的ModelViewSet默认支持表单编码和JSON格式数据,但如果客户端发送的data格式不符合要求,可能导致路由匹配异常。
- 尝试将请求改为发送JSON格式数据:
import json res = requests.post( "http://1.2.3.4:8001/api/strategy/target/", data=json.dumps(data), headers={ 'Authorization': 'Bearer {0}'.format(token), 'Content-Type': 'application/json' } ) - 确认视图的
parser_classes包含FormParser和MultiPartParser(ModelViewSet默认已包含,可显式指定排查)。
5. 修正路由注册的basename参数
DefaultRouter.register()方法中,手动指定的basename="targets-list"可能与默认生成的路由名称(target-list)冲突,导致路由匹配失败。
- 移除basename参数,使用默认生成的路由名称:
router.register("target", TargetViewSet) - 执行
python manage.py show_urls命令,查看实际生成的路由规则,确认/api/strategy/target/对应POST方法的路由存在。
内容的提问来源于stack exchange,提问作者Florent
相关产品推荐
相关产品推荐

