导读:本期聚焦于崔健创作的《解决 Flask 中 Request 对象没有 body 属性的常见错误》,敬请观看详情。在 Flask 开发中,不少人在处理请求数据时会习惯性地写下 request.body,结果程序直接抛出 AttributeError,提示 Request 对象并不存在 body 属性。这个错误的根源在于 Flask 与 Django 在请求对象设计上的差异,Flask 的 Request 对象提供了 get_data、get_json、form、values 等多种获取请求体的方式,而不是一个统一的 body 属性。本文将详细分析这个报错产生的原因,对比 Flask 与 Django 获取请求数据的不同做法,并结合代码示例讲解如何正确读取原始字节、JSON 数据、表单数据以及文件上传,同时说明各方法的适用场景和常见坑点,帮助你彻底避开这个高频错误。

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

解决 Flask 中 Request 对象没有 body 属性的常见错误

为什么会报 Request 对象没有 body 属性的错误

首先要明确一点:这不是你的环境装错了,也不是 Flask 版本太旧,而是 Flask 从设计上就没有提供 request.body 这个属性。在 Django 中,request.body 返回的是原始请求体的字节串,开发者拿到后可以自行解析,这个设计非常直接。但 Flask 走的是另一条路,它根据 Content-Type 和数据形态,把请求体拆分成了多个独立的属性和方法,比如 request.get_data()request.get_json()request.formrequest.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 或 listContent-Type 为 application/json 的接口
request.formImmutableMultiDictHTML 表单提交、键值对数据
request.valuesCombinedMultiDict同时兼容 URL 参数和表单参数
request.filesFileStorage 对象文件上传

还有一点必须提醒:请求体是流式数据,只能读取一次。如果你先调用了 get_data(),后面再访问 request.formrequest.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.bodyget_json() 处理 JSON,form 处理表单,files 处理文件。搞清楚这些,这个错误以后就不会再困扰你了。

Flask Request Flask request.body Flask 获取请求体修改时间:2026-09-08 05:26:32

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260908/52605.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。