request.form仅解析application/x-www-form-urlencoded和multipart/form-data两种content-type,其余类型不解析;request.data原样返回字节流,需手动解码;request.json仅在content-type为application/json且可解析时有效。

request.form 只认两种 Content-Type,其他一律无视
它不是“没收到数据”,是压根不解析——request.form 仅在请求头 Content-Type 为 application/x-www-form-urlencoded 或 multipart/form-data 时才从请求体中提取键值对。浏览器原生 <form></form> 提交、Postman 的 “Form Data” 模式、或 axios 配了 { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } } 才能触发它。
- 若前端发的是 raw JSON(
Content-Type: application/json),request.form永远是空的ImmutableMultiDict([]) - 若用 fetch 发表单但忘了设
Content-Type,后端看到的可能是text/plain或空头,request.form同样收不到 -
request.form.get("key")返回None不代表前端没传,很可能是类型不匹配
request.data 是原始请求体的“照单全收”
request.data 是字节流(bytes),不管 Content-Type 是啥,只要请求体里有东西,它就给你原样吐出来。但它不会自动解码、不会拆成字典——你得自己 .decode()、json.loads() 或 parse_qs()。
- 发 JSON:前端设
Content-Type: application/json→ 后端用request.data.decode()+json.loads() - 发纯文本:
request.data.decode('utf-8')即可拿到字符串 - 发表单但
Content-Type错了(比如漏配):request.data里有b'username=zs&password=123456',可用urllib.parse.parse_qs()手动解析 - 注意:
request.data和request.form是互斥读取的——一旦request.form成功解析,request.data就变空了(b'')
别混用 request.json —— 它比 request.data 更挑食
request.json 看似方便,但它只在 Content-Type 明确为 application/json 且内容可 JSON 解析时才返回字典;否则直接返回 None,连异常都不抛。它不帮你 fallback,也不管你是不是发了个带 BOM 的 UTF-8 JSON。
- 错误示范:
Content-Type: text/plain+ JSON 字符串 →request.json是None,但request.data还有救 - 安全写法:优先检查
request.is_json,再取request.json;否则退到request.data自行处理 - 调试时打印
request.headers.get('Content-Type')比猜更可靠
Postman / curl 测试时最容易翻车的三个点
接口通不了?八成卡在这三处:
- Postman 选了 “Body → form-data”,但后端写了
request.json—— 类型错配,两边都以为对方有问题 - curl 发 JSON 忘加
-H "Content-Type: application/json",后端用request.form死等,结果等来个空字典 - 前端用
axios.post(url, { a: 1 })默认发 JSON,但后端只写了request.form.get('a')—— 数据在 body 里,却去 form 里翻抽屉
复杂点在于:同一个接口可能要兼容表单提交和 API 调用,这时候不能只靠一个属性兜底;必须根据 Content-Type 分支处理,或者统一用 request.get_data() 配合手动解析。










