请求与响应 - 处理请求数据
大家好,这个章节我们来学习一下在 Flask 中如何处理请求数据。
简介
当浏览器去访问一个地址时,HTTP 协议会向后台传递一个请求对象。这个请求对象包含请求头、请求参数、以及请求方式。后台可以取到这个请求对象,然后进行逻辑处理。
当你在浏览器里输入一个网址访问某个页面时,浏览器会通过 HTTP 协议向服务器发送一个请求。这个请求包含了很多信息,比如请求的头部、参数、以及请求的方式(GET、POST等)。Flask 在后台会接收到这个请求对象,然后你可以根据这个请求来进行相应的处理。
request 对象
在 Flask 中,可以使用 request 对象来处理请求数据。request 对象提供了访问请求数据的相关方法和属性。
详情可以查阅官方文档。
在 Flask 中,我们通过 request 对象来访问请求的数据。这个对象提供了很多方法和属性,帮助我们获取请求中的各种信息,比如请求参数、请求体、请求头等。如果你想深入了解 request 的所有功能,可以查看 Flask 的官方文档。
request 的常用属性/方法
以下是一些常见的处理请求数据的方法:
属性/方法 | 说明 |
---|---|
args | 记录请求中的查询参数 |
json | 记录请求中的 json 数据 |
files | 记录请求上传的文件 |
form | 记录请求中的表单数据 |
method | 记录请求使用的 HTTP 方法 |
url | 记录请求的 URL 地址 |
host | 记录请求的域名 |
headers | 记录请求的头信息 |
request 对象有很多常用的属性和方法,这些都帮助我们获取请求中的不同数据。比如,request.args 用来获取 URL 中的查询参数,request.json 用来获取 JSON 格式的请求体数据,request.form 用来获取表单数据,request.files 则用来获取上传的文件,request.method 可以查看请求的类型,request.url 和 request.host 用来获取请求的 URL 和域名,request.headers 则是请求头信息。这些方法可以让我们灵活地处理不同类型的请求。
普通请求参数处理
如果一个 GET 请求在 URL 中拼接了请求参数,可以使用 request.args
来获取 GET 请求中携带的请求参数。request.args
是一个字典,可以通过键名来获取参数的值。
from flask import Flask, request
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route('/user')
def get_user():
# 获取 URL 中的请求参数
url_param = request.args
# 查看获取到的请求参数的类型
print(type(url_param))
# 获取请求参数中的 username 对应的值
username = url_param.get('username')
return f'Hello, {username}!'
# 运行应用程序
if __name__ == '__main__':
app.run()
对于 GET 请求,参数通常会出现在 URL 中,比如 /user问好username=John。我们可以通过 request点args 来获取这些参数,它返回的是一个字典,可以像平时一样用 点get() 方法来获取某个参数的值。
访问 /user?username=John
,将返回 'Hello, John!'
。
查看服务端日志信息,可以看到 request.args
取到的值的数据类型为 werkzeug.datastructures.structures.ImmutableMultiDict,也是一个可迭代的对象,访问方法和基础的字典类似。想要获取这个字典中 username
对应的值,可以直接使用 get()
方法。
比如,如果你访问 /user问号username=John,接口接收到这个请求后,在视图函数中使用 request点args点get('username') 获取到 John 这个值。然后返回了 Hello, John! 给客户端。这时如果我们去看一下服务端的日志,也能看到 request点args 取到的值的数据类型为 werkzeug点datastructures点structures点ImmutableMultiDict,这也是一个可迭代的对象,访问方法和基础的字典类似。
JSON 请求体处理
如果是 POST 或者 PUT 相关的请求,需要带有 JSON 数据格式,可以使用 request.json
来获取 POST 请求中的 JSON 数据。request.json
会解析请求的 JSON 数据,并返回一个包含解析后的数据的字典,然后可以根据需要获取特定的字段值。
from flask import Flask, request
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route('/data', methods=['POST'])
def process_data():
# 获取 JSON 格式请求体
data = request.json
# 查看获取到的请求参数的类型
print(type(data))
# 获取请求体中对应字段的值
name = data.get('name')
age = data.get('age')
return f'Name: {name}, Age: {age}'
# 运行应用程序
if __name__ == '__main__':
app.run()
对于 post 或 put 请求,常常会发送一些 JSON 格式的数据。在 Flask 中,我们可以通过 request.json 来获取这些 JSON 数据。Flask 会自动解析 JSON 内容并把它转换成字典,然后你就可以像操作字典一样获取具体的字段。来看下这个例子。对于视图函数 process_data 我们设置了路由为 /data,请求方法为 post。然后在视图函数中,我们先使用 request点json 获取到了 JSON 格式的请求体中的数据。然后打印了一下这个请求数据的类型。接下来就按照访问字典的方式,从请求数据里取出了 name、age 这两个值,并且把这两个值拼接成字符串返回给了客户端。
提交 JSON 格式请求体,请求体中包含姓名和年龄,将返回姓名和年龄的信息。
启动服务后,我们可以使用 postman 来发出一个对 /data 路由的 post 请求。发请求时,可以在请求体中发送一个包含 name 和 age 字段的 JSON 数据,然后我们就可以在响应数据中看到返回给我们的字符串了。
表单请求体处理
如果是 POST 相关的请求,需要带有 form 表单格式数据格式,可以使用 request.form
来获取 POST 请求中的表单数据。request.form
是一个字典,可以通过键名来获取表单字段的值。
from flask import Flask, request
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route('/login', methods=['POST'])
def login():
# 获取表单格式请求体
user_info = request.form
# 查看获取到的请求参数的类型
print(type(user_info))
# 获取请求体中对应字段的值
username = user_info.get('username')
password = user_info.get('password')
return f'Welcome, {username}!'
# 运行应用程序
if __name__ == '__main__':
app.run()
当请求中包含表单数据时,特别是通过 HTML 表单提交的 POST 请求,Flask 提供了 request点form 来获取表单数据。同样的,这也是一个类似于字典的类型,可以通过键名来获取对应的值。来看下这个例子。对于视图函数 login 我们设置了路由为 /login,请求方法为 post。然后在视图函数中,我们先使用 request点form 获取到了表单格式的请求体中的数据。然后打印了一下这个请求数据的类型。接下来就按照访问字典的方式,从请求数据里取出了 username、password 这两个值,并且把用户名拼到欢迎的字符串中返回给了客户端。
通过提交包含用户名和密码的表单,将返回欢迎信息。
启动服务后,我们可以使用 postman 来发出一个对 /login 路由的 post 请求。发请求时,可以在请求体中发送一个包含 username 和 password 字段的 form 表单格式的请求数据,然后我们就可以在响应数据中看到返回给我们的字符串了。
文件请求体处理
如果页面上需要提交一个图片,或者上传一个文件到后端服务器,可以使用 request.files
来获取请求中包含的文件。request.files
是一个字典,每个上传的文件都会存储在这个字典里。可以通过 file
这个 key 来获取其中的文件对象。
已上传的文件存储在内存或是文件系统中一个临时的位置。它有一个 save()
方法,这个方法允许把文件保存到服务器的文件系统上。
如果想知道上传前文件在客户端的文件名是什么,可以访问 filename
属性。但这个值是可以伪造的。如果要把文件按客户端提供的文件名存储在服务器上,需要把它传递给 Werkzeug 提供的 secure_filename()
函数。这个函数可以用来确保文件名是安全的。
from flask import request
from werkzeug import secure_filename
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
# 获取文件格式请求体
file = request.files
# 查看获取到的请求参数的类型
print(type(file))
# 获取请求体中对应字段的值
f = file.get("file")
# 保存文件
# 需要提前创建 uploads 目录,secure_filename 可以确保文件名安全
f.save('./uploads/' + secure_filename(f.filename))
return f'File {f.filename} is saved!'
# 运行应用程序
if __name__ == '__main__':
app.run()
如果页面上需要提交一个图片,或者上传一个文件到后端服务器 ,Flask 提供了 request点files 来获取上传的文件。这也是一个类似字典的类型。可以通过 file 这个 key 来获取其中的文件对象。上传的文件会存储在临时位置,之后可以通过 save() 方法将其保存到服务器指定的位置。为了确保文件名的安全性,还可以使用 secure_filename() 函数来处理文件名,避免不安全的文件名导致安全问题。在这个例子中,先定义了视图函数 upload_file,然后给它设置了路由为 /upload,请求方法为 post。然后在视图函数中,我们先使用 request点files 获取到了文件格式的请求体中的数据。然后打印了一下这个请求数据的类型。接下来就按照访问字典的方式,通过 file 这个 key 从请求数据里取出了文件对象。接下来使用这个文件对象调用 save 方法,把文件存入服务端。save 方法接收两个参数,第一个是文件保存的路径,第二个可以使用 secure_filename 方法传入文件名来保证文件名是安全的。这样请求传过来的文件就成功保存到了服务端。最后并且把保存成功的字符串返回给了客户端。这里要注意,save 方法中传入的文件保存目录必须是已经存在的,如果不存在会报错。
通过提交包含文件的请求体,将返回文件保存息。
启动服务后,我们可以使用 postman 来发出一个对 /upload 路由的 post 请求。发请求时,可以在请求体中发送一个文件,然后我们就可以在响应数据中看到返回给我们的字符串了。再查看一下服务端的目录,可以看到这个文件也被成功保存了。
其他请求参数处理
如果在进行业务处理的时候,需要根据不同的请求 URL、域名、请求参数或者请求头信息进行不同场景的判断,则可以使用以下方法获取对应的值。
from flask import request
from werkzeug import secure_filename
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
# 获取请求 URL
r_url = request.url
# 获取请求域名
r_host = request.host
# 获取请求头信息
r_headers = request.headers
# 获取请求方法
r_method = request.method
print(r_url, r_host, r_headers, r_method)
# 获取文件请求体
r_file = request.files
# 判断请求方法为 POST
if r_method == 'POST':
# 判断请求头中包含 My-Header 字段并且值为 hogwarts
if r_headers.get('My-Header') == "hogwarts":
# 保存文件
f = r_file.get("file")
f.save('./uploads/' + secure_filename(f.filename))
return f'File {f.filename} is saved! URL is {r_url}, host is {r_host}'
return f"My-Header is missing!"
return f"Method is wrong!"
# 运行应用程序
if __name__ == '__main__':
app.run()
除了常见的请求参数和请求体,Flask 还提供了其他方法,帮助我们在处理请求时做更复杂的判断。比如,我们可以获取请求的 URL 地址、域名、请求方法、请求头信息等。通过这些信息,就可以做更精细的逻辑判断。而且我们也可以设置一个视图函数能接受多种方式的请求,然后在视图函数内部根据不同的请求方法,比如 get 或 post,或者根据特定的请求头信息来处理不同的业务逻辑。这里我们在上一个例子的基础上,增加了请求方法的支持,然后又判断只有当请求方法为 post 时,并且请求头中要包含 My Header 的值为 hogwarts,这个时候才会接收传来的文件并保存。其他场景下都只是返回了提示字符串。
这样就可以校验请求方法、请求头信息,然后再完成对应的业务逻辑处理了。
启动服务后,我们给刚才 postman 中的请求再添加一个请求头信息,然后我们就可以在响应数据中看到返回给我们的字符串了。再查看一下服务端的目录,可以看到这个文件也被成功保存了。大家看,通过这种方式,这样就可以校验请求方法、请求头信息,然后再完成对应的业务逻辑处理了。
总结
- request 的常用属性/方法
- 普通请求参数处理
- JSON 请求体处理
- 表单请求体处理
- 文件请求体处理
- 其他请求参数处理
最后再来总结一下。这个章节介绍了 Flask 中 request 对象的一些常用属性和方法,包括如何处理 GET 请求参数、JSON 请求体、表单数据、文件上传以及其他请求参数。理解这些内容后,你就能更加灵活地处理来自客户端的请求了。