从 Django 转到 Flask 的开发者,十有八九都踩过一个坑:想读取请求体时顺手写了 request.body,运行后 Flask 直接抛出 AttributeError: 'Request' object has no attribute 'body'。这个报错信息本身很好理解——Flask 的 Request 对象确实没有 body 属性,但问题是怎么正确地拿到请求数据。这篇文章就来把这个错误彻底讲清楚,包括它产生的原因、Flask 提供的正确 API,以及不同数据格式下应该用哪种方式读取。

为什么会报 Request 对象没有 body 属性的错误
首先要明确一点:这不是你的环境装错了,也不是 Flask 版本太旧,而是 Flask 从设计上就没有提供 request.body 这个属性。在 Django 中,request.body 返回的是原始请求体的字节串,开发者拿到后可以自行解析,这个设计非常直接。但 Flask 走的是另一条路,它根据 Content-Type 和数据形态,把请求体拆分成了多个独立的属性和方法,比如 request.get_data()、request.get_json()、request.form、request.files 等,每种数据类型都有专门的入口。
这种设计的出发点是让常用场景更省事。处理表单直接访问 request.form,处理 JSON 直接调用 request.get_json(),不需要手动去解析原始字节。但代价就是习惯了 Django 或 Express(Express 中是 req.body)的开发者,第一次接触 Flask 时很容易凭直觉写出 request.body,然后被这个 AttributeError 拦住。
来看一个典型的报错场景:
from flask import Flask, request
app = Flask(__name__)
@app.route('/api/data', methods=['POST'])
def get_data():
# 错误写法:Flask 的 Request 对象没有 body 属性
data = request.body # 这里会抛出 AttributeError
return {'received': True}
运行后访问这个接口,控制台会输出类似 AttributeError: 'Request' object has no attribute 'body' 的错误。定位问题的方法也很简单,打开 Python 交互环境,用 dir(request) 查看一下 Request 对象的全部属性和方法,你会发现列表里有 get_data、get_json、form、data 等,唯独没有 body。
Flask 中获取请求体的正确姿势
既然没有 body 属性,那就得用 Flask 提供的标准方法。根据客户端发送数据的格式不同,常用的有下面几种方式,需要根据实际情况选择。
获取原始字节:get_data 方法
如果你只是想拿到原始的请求体字节串,和 Django 的 request.body 最接近的是 Flask 的 request.get_data() 方法:
from flask import Flask, request
app = Flask(__name__)
@app.route('/api/raw', methods=['POST'])
def get_raw():
# 获取原始请求体,返回 bytes 类型,等价于 Django 的 request.body
raw_data = request.get_data()
print(raw_data) # 例如 b'{"name": "tom", "age": 18}'
print(type(raw_data)) # <class 'bytes'>
return {'length': len(raw_data)}
需要注意的是,get_data() 返回的是 bytes 类型,如果要当字符串处理,需要手动解码,例如 raw_data.decode('utf-8')。另外还有一个 request.data 属性也能拿到原始字节,效果和 get_data() 基本一致,但 get_data() 支持传入 as_text=True 参数直接返回字符串,用起来更灵活一些。
获取 JSON 数据:get_json 方法
现在的接口大部分都是 JSON 格式,Flask 处理 JSON 的推荐方式是 request.get_json():
from flask import Flask, request
app = Flask(__name__)
@app.route('/api/json', methods=['POST'])
def get_json_data():
# 客户端必须设置 Content-Type: application/json
data = request.get_json()
name = data.get('name')
age = data.get('age')
return {'name': name, 'age': age}
这里有一个非常高频的坑:如果客户端发送请求时没有把 Content-Type 设置为 application/json,get_json() 会解析失败并返回 400 错误,或者在旧版本中返回 None。解决办法有两种,一是确保客户端请求头正确,二是调用时加上 force=True 参数,让 Flask 忽略 Content-Type 强制按 JSON 解析:request.get_json(force=True)。还可以配合 silent=True,解析失败时不报错而是返回 None,方便自己做容错处理。
获取表单数据:form 属性
如果客户端提交的是传统表单(Content-Type 为 application/x-www-form-urlencoded 或 multipart/form-data),应该使用 request.form:
from flask import Flask, request
app = Flask(__name__)
@app.route('/api/form', methods=['POST'])
def get_form_data():
username = request.form.get('username')
password = request.form.get('password')
return {'username': username}
另外还有一个 request.values 属性,它合并了 URL 查询参数和表单数据,适合不确定参数在 URL 里还是请求体里的场景。而文件上传则要使用 request.files,通过 request.files['file'] 拿到文件对象后,再调用 save() 方法保存到磁盘。
不同获取方式的对比与选择建议
面对这么多种获取请求数据的方式,新手常常不知道该用哪个。下面这张表整理了它们各自的适用场景:
| 方式 | 返回类型 | 适用场景 |
|---|---|---|
| request.get_data() | bytes | 获取原始字节,对接非标准格式或需要自行解析的场景 |
| request.get_json() | dict 或 list | Content-Type 为 application/json 的接口 |
| request.form | ImmutableMultiDict | HTML 表单提交、键值对数据 |
| request.values | CombinedMultiDict | 同时兼容 URL 参数和表单参数 |
| request.files | FileStorage 对象 | 文件上传 |
还有一点必须提醒:请求体是流式数据,只能读取一次。如果你先调用了 get_data(),后面再访问 request.form 或 request.get_json(),可能拿不到数据。不过 Flask 内部对此做了一定缓冲处理,多次调用 get_data() 本身是安全的,因为默认情况下请求体会被缓存。但如果使用了某些中间件或者流式处理逻辑,重复读取就可能出问题。实际开发中建议在一个请求处理函数里只选用一种合适的方式来读取数据,不要混用多种读取手段。
对于需要区分多种 Content-Type 的通用接口,可以参考下面这种写法,先判断再分支处理:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/api/universal', methods=['POST'])
def universal():
if request.is_json:
# JSON 请求
data = request.get_json()
elif request.form:
# 表单请求
data = dict(request.form)
else:
# 其他格式,读取原始字节
data = request.get_data(as_text=True)
return jsonify({'data': data})
总结一下,Flask 报 Request 对象没有 body 属性的错误,本质上是因为它用一组更细粒度的 API 替代了统一的 body 属性。记住几个核心对应关系:get_data() 等价于 Django 的 request.body,get_json() 处理 JSON,form 处理表单,files 处理文件。搞清楚这些,这个错误以后就不会再困扰你了。
Flask Request Flask request.body Flask 获取请求体修改时间:2026-09-08 05:26:32