暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Flask 用户指南 - 快速入门(4)

数据库杂货铺 2022-02-09
218

访问请求数据

 

对于 web 应用程序来说,对客户端发送给服务器的数据做出反应是至关重要的。在 Flask 中,这个信息是由全局 request 对象提供的。如果你有一些 Python 的经验,你可能会想知道这个对象如何是全局的,以及 Flask 如何仍然是线程安全的。答案是本地上下文:

 

本地上下文

 

内部信息

 

如果想了解它是如何工作的,以及如何使用本地上下文实现测试,请阅读本部分,否则直接跳过。

 

Flask 中的某些对象是全局对象,但不是通常所说的全局。这些对象实际上是特定上下文的本地对象的代理。说起来有点儿拗口,但这其实很容易理解。

 

假设上下文是处理线程。此时出现一个请求,web 服务器决定生成一个新线程。当 Flask 开始内部请求处理时,它会发现当前线程是活动上下文,并将当前应用程序和 WSGI 环境绑定到该上下文(线程)。它以一种智能的方式实现这一点,这样一个应用程序就可以调用另一个应用程序而不会中断。

 

这对你来说意味着什么?基本上,你可以完全忽略这种情况,除非你在做单元测试之类的事情。你会注意到,依赖于请求对象的代码会突然中断,因为没有请求对象。解决方案是自己创建一个请求对象,并将其绑定到上下文。单元测试最简单的解决方案是使用 test_request_context() 上下文管理器。结合 with 语句,它将绑定一个测试请求,以便你可以与之交互。下面是一个例子:

 

from flask import request


with app.test_request_context('/hello', method='POST'):
# now you can do something with the request until the
# end of the with block, such as basic assertions:
assert request.path == '/hello'
assert request.method == 'POST'
复制

 

另一种可能是将整个 WSGI 环境传递给 request_context() 方法:

 

with app.request_context(environ):
assert request.method == 'POST'
复制

 

请求对象

 

请求对象记录在 API 部分中,我们将不在这里详细介绍它。下面是一些最常见操作的概述。首先必须从 flask 模块导入它:

 

from flask import request
复制

 

使用 method 属性可以获取当前请求方法。要访问表单数据(POST PUT 请求中传输的数据),可以使用 form 属性。以下是上述两个属性的完整示例:

 

@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
复制

 

如果 form 属性中不存在请求的参数,会发生什么?在这种情况下,会引发一个特殊的 KeyError 错误。可以像捕获标准的 KeyError 错误一样捕获它,但如果不这样做,则会显示 HTTP 400 Bad Request 错误页面。所以在很多情况下,你不必处理这个问题。

 

要访问 URL 中提交的参数(?key=value),可以使用 args 属性:

 

searchword = request.args.get('key', '')
复制

 

建议使用 get 或通过捕获 KeyError 来访问 URL 参数,因为用户可能会更改 URL,他们会看到 400 错误请求页面,在这种情况下对用户不友好。

 

文件上传

 

可以用 Flask 轻松处理上传的文件,只需确保不要忘记在 HTML 表单上设置属性 enctype="multipart/form-data",否则浏览器根本不会传输文件。

 

上传的文件存储在内存中或文件系统上的临时位置。通过查看请求对象上的 files 属性,可以访问这些文件。每个上传的文件都存储在字典中。它们就像标准的 Python 文件对象,但它还有一个 save() 方法,允许将该文件存储在服务器的文件系统中。下面是一个简单的例子,展示了它的工作原理:

 

from flask import request


@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
...
复制

 

如果想知道文件在上传到应用程序之前是如何在客户端命名的,可以访问 filename 属性。但是请记住,这个值是可以伪造的,所以永远不要相信这个值。如果要使用客户端的文件名在服务器上存储文件,请通过 Werkzeug 为您提供的 secure_filename() 函数传递:

 

from werkzeug.utils import secure_filename


@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['the_file']
file.save(f"/var/www/uploads/{secure_filename(file.filename)}")
...
复制

 

Cookie

 

要访问 cookie,可以使用 cookies 属性。要设置 cookie,可以使用响应对象的 set_cookie 方法。请求对象的 cookies 属性是一个包含客户端传输的所有 cookie 的字典。如果想使用会话,不要直接使用 cookie,而是使用 Flask 中的 session,这在 cookie 之上添加一些安全性。

 

读取 cookie

 

from flask import request


@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a
# KeyError if the cookie is missing.
复制

 

存储 cookie:

 

from flask import make_response


@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp
复制

 

请注意,cookie 是在响应对象上设置的。由于通常只从视图函数返回字符串,Flask 将为您将其转换为响应对象。如果明确希望这样做,可以使用 make_response() 函数,然后对其进行修改。

 

有时可能希望在响应对象尚不存在的时候设置 cookie。这可以通过使用延迟请求回调模式来实现。

 

 

 

原文:

https://flask.palletsprojects.com/en/2.0.x/quickstart/

文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论