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

Django REST Framework中detail_route的PUT请求无末尾斜杠时请求体为空的原因探究

问题成因详解:DRF detail_route接口无斜杠时请求体为空

这个问题其实是Django默认的URL规则和HTTP客户端行为共同作用的结果,我给你一步步拆解清楚为什么会出现这种「无报错但请求体为空」的情况:

1. Django默认的APPEND_SLASH机制

Django项目默认开启了APPEND_SLASH = True(在settings.py中),这个设置的核心逻辑是:当请求的URL末尾没有斜杠,且路由系统找不到匹配的条目时,它会自动检查添加末尾斜杠后的URL是否存在匹配项。如果存在,就返回301 Moved Permanently重定向响应,引导客户端访问带斜杠的正确URL。

在你的场景里,router.register生成的detail_route接口URL是带末尾斜杠的(即/my_resource/history/),当你请求不带斜杠的/my_resource/history时,Django找不到对应的路由,直接触发了这个重定向逻辑。

2. HTTP客户端对301重定向的PUT请求处理

当requests库收到301重定向响应时,它会自动按照响应的Location头发起新的PUT请求到带斜杠的URL,但这里有个关键细节:重定向后的PUT请求不会携带原请求体。

这是因为HTTP标准中,301重定向的语义是「永久移动」,对于PUT这类有副作用的非GET请求,客户端为了避免重复执行可能产生的意外影响(比如重复修改资源),通常不会自动携带原请求体发起第二次请求。requests库的默认行为就是如此,所以第二次PUT请求的body是空的。

3. 为什么没有报错?

因为重定向后的URL是完全有效的(匹配到了你的history detail_route),DRF会正常处理这个请求——只是此时请求体是空的,所以你的print(request.body)输出空内容,但不会返回404或其他错误响应。

快速验证方法

你可以关闭自动重定向,直接查看第一次请求的状态码来确认这个逻辑:

response = requests.put(url, data=json.dumps({'test': 'passed'}), allow_redirects=False)
print(response.status_code)  # 会输出301
print(response.headers['Location'])  # 会指向带斜杠的目标URL

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:42:31