Flask - 当内容类型为 "application/x-www-form-urlencoded" 时,如何读取 POST 请求的原始数据体?

22

原来 Flask 在请求的内容类型为 application/x-www-form-urlencoded 时将 request.data 设置为空字符串。由于我使用的是 JSON 请求体,因此我只想解析 JSON 或者让 Flask 解析它并返回 request.json

这是必需的,因为更改 AJAX 内容类型会强制进行 HTTP OPTION 请求,这会使后端变得复杂。

如何使 Flask 返回请求对象中的原始数据?


没错,flask.request.data.decode("utf-8") 是空的,但我以为是客户端的问题。谢谢确认是 Flask 完成的!哇塞,10年后再次遇见这个对话,今天真的帮了我大忙!之前我还困惑了几个小时呢。 - HeyWatchThis
7个回答

19

如果内容类型是application/x-www-form-urlencoded,您可以通过request.form.keys()[0]获取帖子数据。

request.form是一个MultiDict,其键包含解析后的帖子数据。


3
看起来这也是从帖子到瓶子中获取数据的方法。只需将request.form.keys()[0]更改为list(request.forms.keys())[0]即可。感谢您最终解决了数小时的调试! - Emil Stenström
有人能解释一下为什么数据被放入表单键中吗? - JMStudios.jrichardson
如果数据包含“=”和“&”字符,则此方法不会提供所有的提交数据。 - Mark
1
@Emil 应该是表单而不是表格。 - PallavBakshi
1
我会使用 form.keys 并从那里开始获取你所需的数据。get_data() 返回一个字节流,只有在处理二进制数据时才有用。 - Nelson
显示剩余3条评论

13

使用request.get_data()来获取POST数据。这可以独立于数据的内容类型是application/x-www-form-urlencoded还是application/octet-stream


2
这似乎不是这样。根据我收到的请求,如果我使用get_data(),我会得到一个空的bytes(),但是使用被接受的答案中的方法(查看表单键)我可以得到一堆数据。 - Jack M
2
我也是,get_data()方法什么也没有,但按照被接受的答案这样做似乎很荒谬。 - Dalbenn
这对我来说很合适。谢谢 :) - Qudor Eng

5
如果您想在请求为“Content-Type:application/x-www-form-urlencoded”时获取JSON,则需要像下面的代码一样进行“强制”转换为json:

from flask import Flask, request
import os


app = Flask(__name__)


@app.route("/my-endpoint", methods = ['POST'])
def myEndpoint():

    requestJson = request.get_json(force=True)

    //TODO: do something....

    return requestJson


if __name__ == "__main__":
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port, debug=True, use_reloader=True)

可能它现在已经过时了,所以它不再起作用。 - John

1

main.py

import json

from flask import Flask, request

app = Flask(__name__)


@app.route('/', methods=['POST'])
def index():
    mimetype = request.mimetype
    if mimetype == 'application/x-www-form-urlencoded':
        form = json.loads(next(iter(request.form.keys())))
    elif mimetype == 'multipart/form-data':
        form = dict(request.form)
    elif mimetype == 'application/json':
        form = request.json
    else:
        form = request.data.decode()
    print(mimetype, form, type(form))
    return form


if __name__ == '__main__':
    app.run()

测试

curl -X POST http://127.0.0.1:5000/ --data "{\"a\":1, \"b\":2}"

curl -X POST http://127.0.0.1:5000/ -F a=1 -F b=2

curl -X POST -H "Content-type: application/json" http://127.0.0.1:5000/ --data "{\"a\":1, \"b\":2}"

结果

application/x-www-form-urlencoded {'a': 1, 'b': 2} <class 'dict'>
multipart/form-data {'a': '1', 'b': '2'} <class 'dict'>
application/json {'a': 1, 'b': 2} <class 'dict'>

1
你可以这样获取它:
@app.route("/path-to-the-post-endpoint", methods=["POST"])
def handle_post_request():
    data = request.form.to_dict()
    data['some_key_1'] = "Some Value 1"
    data['some_key_2'] = "Some Value 2"
    # ...etc.

    # DO SOMETHING HERE

    return [], 200

我的POST请求Content-Type是application/x-www-form-urlencoded,我想将其转换为字典。这个方法对我很有效:request.form.to_dict() - Athif Saheer

0

request.values会获取argspost,优先考虑args,详见Python docs

request.json将处理JSON负载。


0

试试这个:

f = request.form

   output = []

   user_data = {}

   user_data['email'] = f['email']

   user_data['password'] = f['password']

   user_data['key'] = f['key']

   output.append(user_data)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接