如何在 Flask 中处理收到的请求数据

介绍

网页应用程序通常需要处理用户的输入请求数据,这种负载可以以查询字符串、表单数据和 JSON 对象的形式。

在本教程中,您将构建一个使用三个路径的Flask应用程序,这些路径可以接受查询字符串、表单数据或JSON对象。

前提条件

要完成本教程,您将需要:

本教程已通过 Pipenv v2020.11.15、Python v3.9.0 和 Flask v1.1.2 进行验证。

创建项目

尽管示例应用程序使用了视图函数和路径的简化结构,但您在本教程中学到的内容可以应用于组织视图的任何方法,例如基于类的视图,蓝图或Flask-Via等扩展。

首先,您需要创建一个项目目录. 打开终端并运行以下命令:

1mkdir flask_request_example

然后,导航到新目录:

1cd flask_request_example

接下来,安装Flask,打开终端并执行以下命令:

1pipenv install Flask

pipenv命令将为该项目创建一个 virtualenv、一个Pipfile、安装flask和一个Pipfile.lock。

要激活项目的 virtualenv,运行以下命令:

1pipenv shell

要访问 Flask 中的输入数据,您必须使用请求对象. 请求对象包含请求的所有输入数据,其中包括模型、引用、IP 地址、原始数据、HTTP 方法和标题等。

虽然请求对象的所有信息都可能有用,但对于本文的目的,您将专注于通常由终端点的呼叫者直接提供的数据。

要访问 Flask 中的请求对象,您需要从 Flask 库导入它:

1from flask import request

然后你有能力在你的任何视图功能中使用它。

使用代码编辑器创建app.py文件,导入Flaskrequest对象,并为query-example,form-examplejson-example建立路线:

 1[label app.py]
 2# import main Flask class and request object
 3from flask import Flask, request
 4
 5# create the Flask app
 6app = Flask(__name__)
 7
 8@app.route('/query-example')
 9def query_example():
10    return 'Query String Example'
11
12@app.route('/form-example')
13def form_example():
14    return 'Form Data Example'
15
16@app.route('/json-example')
17def json_example():
18    return 'JSON Object Example'
19
20if __name__ == '__main__':
21    # run app in debug mode on port 5000
22    app.run(debug=True, port=5000)

接下来,打开终端并使用以下命令启动应用程序:

1python app.py

该应用程序将在端口5000上启动,因此您可以通过以下链接在浏览器中查看每个路线:

1http://127.0.0.1:5000/query-example (or localhost:5000/query-example)
2http://127.0.0.1:5000/form-example (or localhost:5000/form-example)
3http://127.0.0.1:5000/json-example (or localhost:5000/json-example)

该代码建立了三个路径,访问每个路径将显示查询字符串示例表单数据示例JSON对象示例的信息。

使用 Query 论点

您添加到查询字符串的 URL 参数是传输数据到 Web 应用程序的常见方法. 在浏览 Web 时,您可能已经遇到过查询字符串。

一个查询字符串看起来如下:

1example.com?arg1=value1&arg2=value2

查询字符串在问号(?)字符之后开始:

1example.com?arg1=value1&arg2=value2

并且具有由 ampersand (&) 字符分开的关键值对:

1example.com?arg1=value1&arg2=value2

对于每个对,接着是等符号(=)字符,然后是值。

1arg1 : value1
2arg2 : value2

查询字符串有助于传输不需要用户采取行动的数据. 您可以在应用程序中的某个地方生成查询字符串,并将其附加到 URL,以便当用户提出请求时,数据会自动传输给他们。

在这个假设的例子中,你将提供一个编程语言的名称,将显示在屏幕上。

1http://127.0.0.1:5000/query-example?language=Python

如果您运行该应用程序并导航到该 URL,您将看到它仍然显示查询字符串示例的消息。

您需要编程处理查询参数的部分,此代码将通过使用request.args.get('language')request.args['language']来读取语言键。

通过调用request.args.get('language'),如果URL中没有language键,应用程序将继续运行。

通过调用request.args[‘language’],如果URL中不存在language键,应用程序将返回400个错误。

在处理查询字符串时,建议使用request.args.get()来防止应用程序失败。

让我们阅读语言键,并将其显示为输出。

在 app.py 中,用以下代码修改查询示例路线:

1[label app.py]
2@app.route('/query-example')
3def query_example():
4    # if key doesn't exist, returns None
5    language = request.args.get('language')
6
7    return '''<h1>The language value is: {}</h1>'''.format(language)

然后,运行应用程序并导航到URL:

1http://127.0.0.1:5000/query-example?language=Python

浏览器应该显示以下信息:

1[secondary_label Output]
2The language value is: Python

URL 中的参数被分配到语言变量,然后返回到浏览器中。

若要添加更多查询字符串参数,您可以将 ampersands 和新钥匙值对附到 URL 的末尾。

1http://127.0.0.1:5000/query-example?language=Python&framework=Flask

如果您想要更多,请继续添加 ampersands 和关键值对,创建一个网站和一个数字海洋值的密钥:

1http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean

若要访问这些值,您仍然会使用request.args.get()request.args[]。 让我们使用这两个值来展示缺少密钥时会发生什么。

 1@app.route('/query-example')
 2def query_example():
 3    # if key doesn't exist, returns None
 4    language = request.args.get('language')
 5
 6    # if key doesn't exist, returns a 400, bad request error
 7    framework = request.args['framework']
 8
 9    # if key doesn't exist, returns None
10    website = request.args.get('website')
11
12    return '''
13              <h1>The language value is: {}</h1>
14              <h1>The framework value is: {}</h1>
15              <h1>The website value is: {}'''.format(language, framework, website)

然后,运行应用程序并导航到URL:

1http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean

浏览器应该显示以下信息:

1[secondary_label Output]
2The language value is: Python
3The framework value is: Flask
4The website value is: DigitalOcean

从URL中删除语言键:

1http://127.0.0.1:5000/query-example?framework=Flask&website=DigitalOcean

浏览器应该在未提供语言值时显示以下消息:

1[secondary_label Output]
2The language value is: None
3The framework value is: Flask
4The website value is: DigitalOcean

从URL中删除框架密钥:

1http://127.0.0.1:5000/query-example?language=Python&website=DigitalOcean

浏览器应该遇到一个错误,因为它正在等待一个框架的值:

1[secondary_label Output]
2werkzeug.exceptions.BadRequestKeyError
3werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
4KeyError: 'framework'

现在您已经了解了处理查询字符串的内容了,让我们继续到下一个类型的输入数据。

使用数据形式

表单数据来自已作为 POST 请求发送到路径的表单,因此,而不是在 URL 中查看数据(除非表单与 GET 请求一起提交),表单数据将被传送到幕后应用程序。

要证明这一点,在app.py中修改form-example路径,以接受 GET 和 POST 请求,然后返回表格:

 1[label app.py]
 2# allow both GET and POST requests
 3@app.route('/form-example', methods=['GET', 'POST'])
 4def form_example():
 5    return '''
 6              <form method="POST">
 7                  <div><label>Language: <input type="text" name="language"></label></div>
 8                  <div><label>Framework: <input type="text" name="framework"></label></div>
 9                  <input type="submit" value="Submit">
10              </form>'''

然后,运行应用程序并导航到URL:

1http://127.0.0.1:5000/form-example

浏览器应该显示两个输入字段的表单 - 一个用于语言和一个用于框架 - 和提交按钮。

最重要的是要知道这个表单是它执行一个 POST 请求到生成表单的相同路径。在应用程序中读取的密钥都来自我们表单输入上的名称属性。

在视图函数中,您需要检查请求方法是否为 GET 或 POST. 如果是 GET 请求,您可以显示表单。

在 app.py 中,用以下代码修改form-example路线:

 1[label app.py]
 2# allow both GET and POST requests
 3@app.route('/form-example', methods=['GET', 'POST'])
 4def form_example():
 5    # handle the POST request
 6    if request.method == 'POST':
 7        language = request.form.get('language')
 8        framework = request.form.get('framework')
 9        return '''
10                  <h1>The language value is: {}</h1>
11                  <h1>The framework value is: {}</h1>'''.format(language, framework)
12
13    # otherwise handle the GET request
14    return '''
15           <form method="POST">
16               <div><label>Language: <input type="text" name="language"></label></div>
17               <div><label>Framework: <input type="text" name="framework"></label></div>
18               <input type="submit" value="Submit">
19           </form>'''

然后,运行应用程序并导航到URL:

1http://127.0.0.1:5000/form-example

填写语言字段以Python值和框架字段以Flask值。

浏览器应该显示以下信息:

1[secondary_label Output]
2The language value is: Python
3The framework value is: Flask

现在您已经理解了处理表单数据,让我们继续到下一个类型的输入数据。

使用 JSON 数据

JSON 数据通常是由呼叫路线的过程构建的。

例如,一个 JSON 对象看起来像这样:

 1{
 2    "language" : "Python",
 3    "framework" : "Flask",
 4    "website" : "Scotch",
 5    "version_info" : {
 6        "python" : "3.9.0",
 7        "flask" : "1.1.2"
 8    },
 9    "examples" : ["query", "form", "json"],
10    "boolean_test" : true
11}

这种结构可以允许传输更复杂的数据,而不是查询字符串和表单数据. 在示例中,您可以看到嵌入的 JSON 对象和一组项目。

在 app.py 中修改表格示例路线以接受 POST 请求,并忽略 GET 等其他请求:

1[label app.py]
2@app.route('/json-example', methods=['POST'])
3def json_example():
4    return 'JSON Object Example'

与用于查询字符串和表单数据的 Web 浏览器不同,对于本文的目的,要发送 JSON 对象,您将使用 Postman发送自定义请求到 URL。

<$>[注] :如果您需要帮助导航邮政员接口的请求,请参阅 官方文档

邮件人中,添加 URL 并将类型更改为 ** POST**. 在身体卡上,更改为 ** raw**,然后从下滑板中选择 ** JSON**。

这些设置是必要的,以便 Postman 能够正确地发送 JSON 数据,因此您的 Flask 应用程序将了解它正在接收 JSON:

1POST http://127.0.0.1:5000/json-example
2Body
3raw JSON

接下来,将以前的 JSON 示例复制到文本输入中。

发送请求,你应该得到JSON 对象示例作为答案,这是相当反气候的,但应该是因为处理 JSON 数据响应的代码尚未写出来。

要读取数据,你必须了解Flask如何将JSON数据翻译成Python数据结构:

任何东西都被转换为Python dict。在JSON中的关键 :对应于somedict,该值在Python中返回 *在Python中的JSON中的数组被转换为列表。由于语法是相同的,这里有一个示例列表: [1,2,3,4,5] *在Python中,JSON对象中的引文中的值变成了字符串 *在Python中,布尔语中的变成了

现在,让我们在代码上工作,读取入口的 JSON 数据。

首先,让我们将 JSON 对象中的所有东西分配到一个变量中,使用 request.get_json()

request.get_json() 将 JSON 对象转换为 Python 数据. 让我们将输入请求数据分配给变量,并通过对 json-example 路径进行以下更改来返回它们:

 1[label app.py]
 2# GET requests will be blocked
 3@app.route('/json-example', methods=['POST'])
 4def json_example():
 5    request_data = request.get_json()
 6
 7    language = request_data['language']
 8    framework = request_data['framework']
 9
10    # two keys are needed because of the nested object
11    python_version = request_data['version_info']['python']
12
13    # an index is needed because of the array
14    example = request_data['examples'][0]
15
16    boolean_test = request_data['boolean_test']
17
18    return '''
19           The language value is: {}
20           The framework value is: {}
21           The Python version is: {}
22           The item at index 0 in the example list is: {}
23           The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)

注意如何访问不是顶级的元素。 ['version']['python'] 用于因为您正在输入嵌入对象,而 ['examples'][0] 用于访问示例数组中的第 0 个索引。

如果与请求一起发送的 JSON 对象没有在视图函数中访问的密钥,那么请求将失败。

 1[label app.py]
 2# GET requests will be blocked
 3@app.route('/json-example', methods=['POST'])
 4def json_example():
 5    request_data = request.get_json()
 6
 7    language = None
 8    framework = None
 9    python_version = None
10    example = None
11    boolean_test = None
12
13    if request_data:
14        if 'language' in request_data:
15            language = request_data['language']
16
17        if 'framework' in request_data:
18            framework = request_data['framework']
19
20        if 'version_info' in request_data:
21            if 'python' in request_data['version_info']:
22                python_version = request_data['version_info']['python']
23
24        if 'examples' in request_data:
25            if (type(request_data['examples']) == list) and (len(request_data['examples']) > 0):
26                example = request_data['examples'][0]
27
28        if 'boolean_test' in request_data:
29            boolean_test = request_data['boolean_test']
30
31    return '''
32           The language value is: {}
33           The framework value is: {}
34           The Python version is: {}
35           The item at index 0 in the example list is: {}
36           The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)

运行应用程序并使用 Postman 提交示例 JSON 请求,在响应中,您将获得以下输出:

1[secondary_label Output]
2The language value is: Python
3The framework value is: Flask
4The Python version is: 3.9
5The item at index 0 in the example list is: query
6The boolean value is: false

现在你了解处理 JSON 对象。

结论

在本文中,您构建了一个使用三个路径的Flask应用程序,可以接受查询字符串、表单数据或JSON对象。

此外,请记住,所有方法都必须解决当缺少钥匙时礼貌地失败的反复考虑。

<$>[警告] **警告:**本文未涵盖的一个主题是清洁用户输入,清洁用户输入将确保应用程序读取的数据不会导致意外失败或绕过安全措施。

如果您想了解更多关于 Flask 的信息,请查看 我们的 Flask 主题页面 有关练习和编程项目。

Published At
Categories with 技术
comments powered by Disqus