升级到新版本 — Flask 文档

来自菜鸟教程
Flask/docs/1.1.x/upgrading
跳转至:导航、​搜索

升级到较新版本

Flask 本身也在变化,就像任何软件都在随着时间的推移而变化一样。 大多数更改都是好的类型,您无需更改代码中的任何内容即可从新版本中获利。

然而,每隔一段时间就会有一些更改确实需要对您的代码进行一些更改,或者有些更改使您可以通过利用 Flask 中的新功能来提高自己的代码质量。

文档的这一部分列举了 Flask 从一个版本到另一个版本的所有更改,以及如何更改代码以获得轻松的更新体验。

使用 pip 命令通过提供 --upgrade 参数来升级现有的 Flask 安装:

$ pip install --upgrade Flask

版本 0.12

对 send_file 的更改

filename 不再自动从类文件对象推断出来。 这意味着以下代码将不再自动具有 X-Sendfile 支持、etag 生成或 MIME 类型猜测:

response = send_file(open('/path/to/file.txt'))

以下任何一项在功能上是等效的:

fname = '/path/to/file.txt'

# Just pass the filepath directly
response = send_file(fname)

# Set the MIME-type and ETag explicitly
response = send_file(open(fname), mimetype='text/plain')
response.set_etag(...)

# Set `attachment_filename` for MIME-type guessing
# ETag still needs to be manually set
response = send_file(open(fname), attachment_filename=fname)
response.set_etag(...)

这样做的原因是某些类文件对象具有无效甚至误导性的 name 属性。 在这种情况下,默默地吞下错误并不是一个令人满意的解决方案。

此外,默认回退到 application/octet-stream 已受到限制。 如果 Flask 猜不出一个或用户没有提供,如果没有提供文件名信息,该函数将失败。


版本 0.11

0.11 在 Flask 发布周期中是一个奇怪的版本,因为它应该是 1.0 版本。 然而,由于发布前的准备时间太长,我们决定先推出 0.11 版本,并删除一些更改以使转换更容易。 如果您一直在跟踪 1.0 的 master 分支,您可能会看到一些意外的变化。

如果您确实跟踪了 master 分支,您会注意到 flask --app 现在已被删除。 您需要使用环境变量来指定应用程序。

调试

Flask 0.11 从 Flask 应用程序中删除了 debug_log_format 属性。 相反,新的 LOGGER_HANDLER_POLICY 配置可用于禁用默认日志处理程序,并且可以设置自定义日志处理程序。


错误处理

错误处理程序的行为已更改。 处理程序的优先级曾经分别基于 errorhandler()register_error_handler() 的装饰/调用顺序。 现在继承层次结构优先,并且执行更具体的异常类的处理程序,而不是更一般的异常类。 有关详细信息,请参阅 错误处理程序

现在尝试在实例上注册处理程序会引发 ValueError

笔记

曾经有一个逻辑错误,允许您只为异常 实例 注册处理程序。 这是意外且完全错误的,因此被替换为仅使用异常类和 HTTP 错误代码注册处理程序的预期行为。


模板

render_template_string() 函数已默认更改为自动转义模板变量。 这更好地匹配 render_template() 的行为。


扩展导入

不推荐使用 flask.ext.foo 形式的扩展导入,您应该使用 flask_foo

旧形式仍然有效,但 Flask 将为您以旧方式导入的每个扩展发出 flask.exthook.ExtDeprecationWarning。 我们还提供了一个名为 flask-ext-migrate 的迁移实用程序,它应该为此自动重写您的导入。


版本 0.10

从 0.9 到 0.10 的最大变化是 cookie 序列化格式从 pickle 变成了专门的 JSON 格式。 进行此更改是为了避免在密钥泄露时攻击者可能造成的损害。 升级时,您会注意到两个主要变化:升级前发出的所有会话都将失效,并且您只能在会话中存储有限数量的类型。 新会话在设计上受到更多限制,只允许 JSON 和一些带有 HTML 标记的元组和字符串的小扩展。

为了不中断人们的会话,可以通过使用 Flask-OldSessions 扩展来继续使用旧的会话系统。

Flask 还开始将 flask.g 对象存储在应用程序上下文而不是请求上下文中。 此更改对您来说应该是透明的,但这意味着您现在可以在没有请求上下文但有应用程序上下文时将内容存储在 g 对象上。 旧的 flask.Flask.request_globals_class 属性被重命名为 flask.Flask.app_ctx_globals_class


0.9 版

简化了从函数返回元组的行为。 如果你返回一个元组,它不再定义你正在创建的响应对象的参数,它现在总是一个 (response, status, headers) 形式的元组,其中必须至少提供一个项目。 如果您依赖旧行为,您可以通过继承 Flask 轻松添加它:

class TraditionalFlask(Flask):
    def make_response(self, rv):
        if isinstance(rv, tuple):
            return self.response_class(*rv)
        return Flask.make_response(self, rv)

如果您维护一个之前使用 _request_ctx_stack 的扩展,如果对您的扩展有意义,请考虑更改为 _app_ctx_stack。 例如,应用上下文堆栈对于连接到数据库的扩展很有意义。 使用应用程序上下文堆栈而不是请求上下文堆栈将使扩展更容易处理请求之外的用例。


版本 0.8

Flask 引入了一个新的会话接口系统。 我们还注意到,实现会话的模块 flask.session 和全局会话对象 flask.session 之间存在命名冲突。 通过这个介绍,我们将会话系统的实现细节移到了一个名为 flask.sessions 的新模块中。 如果您使用了以前未记录的会话支持,我们强烈建议您升级。

如果提交了无效的 JSON 数据,Flask 现在将引发 BadRequest 异常,而不是让默认的 ValueError 冒泡。 这样做的好处是您不再需要处理该错误以避免向用户显示内部服务器错误。 如果您在过去明确地将其记录为 ValueError,您将需要更改它。

由于测试客户端中的错误,当在 with 语句中使用测试客户端时,Flask 0.7 没有触发拆卸处理程序。 这是因为已修复,但如果您依赖此行为,则可能需要对您的测试套件进行一些更改。


版本 0.7

在 Flask 0.7 中,我们在内部清理了大量代码库,并做了一些向后不兼容的更改,使使用 Flask 实现更大的应用程序更容易。 因为我们想让升级尽可能简单,所以我们试图通过提供一个可以简化转换的脚本来解决这些变化引起的问题。

该脚本会扫描您的整个应用程序并生成一个统一的差异,其中包含它认为可以安全应用的更改。 然而,由于这是一个自动化工具,它无法找到所有用例,并且可能会遗漏一些。 我们在内部到处散布了大量弃用警告,以便轻松找到无法升级的代码片段。

我们强烈建议您手动查看生成的补丁文件并仅应用看起来不错的块。

如果您使用 git 作为项目的版本控制系统,我们建议使用 path -p1 < patchfile.diff 应用补丁,然后使用交互式提交功能仅应用看起来不错的块。

要应用升级脚本,请执行以下操作:

  1. 下载脚本:flask-07-upgrade.py

  2. 在您的应用程序目录中运行它:

    $ python flask-07-upgrade.py > patchfile.diff
  3. 查看生成的补丁文件。

  4. 应用补丁:

    $ patch -p1 < patchfile.diff
  5. 如果您使用的是每个模块的模板文件夹,您需要移动一些模板。 以前,如果在名为 admin 的蓝图旁边有一个名为 templates 的文件夹,则对于名为 templates/index.html 的模板文件,隐式模板路径自动为 admin/index.html。 现在已经不是这样了。 现在您需要将模板命名为 templates/admin/index.html。 该工具不会检测到这一点,因此您必须自行完成。

请注意,从 Python 2.7 开始,默认情况下禁用弃用警告。 为了查看可能发出的弃用警告,您必须使用 warnings 模块启用它们。

如果您使用的是 Windows 并且缺少 patch 命令行实用程序,您可以将其作为各种 Unix 运行时环境的一部分用于 Windows,包括 cygwin、msysgit 或 ming32。 svn、hg 或 git 等源代码控制系统也内置支持应用由工具生成的统一差异。 查看版本控制系统的手册以获取更多信息。

请求局部变量中的错误

由于早期实现中的错误,请求本地代理现在在未绑定时引发 RuntimeError 而不是 AttributeError。 如果你之前用 AttributeError 捕捉到这些异常,你现在应该用 RuntimeError 捕捉它们。

此外,如果您依赖将在 Flask 0.11 中删除的功能,send_file() 函数现在会发出弃用警告。 以前在传递文件对象时可以使用 etags 和 mimetypes。 这是不可靠的,并导致一些设置出现问题。 如果您收到弃用警告,请确保更新您的应用程序以使用那里的文件名或禁用 etag 附加并自己附加它们。

旧代码:

return send_file(my_file_object)
return send_file(my_file_object)

新代码:

return send_file(my_file_object, add_etags=False)

升级到新的拆解处理

我们简化了用于请求处理的回调行为。 对于修改响应的事情,after_request() 装饰器继续按预期工作,但对于绝对必须在请求结束时发生的事情,我们引入了新的 teardown_request() 装饰器。 不幸的是,这种更改也使请求后在错误条件下的工作方式有所不同。 如果发生异常,它不会一直被跳过,而以前它可能会被调用两次以确保它在请求结束时执行。

如果您有如下所示的数据库连接代码:

@app.after_request
def after_request(response):
    g.db.close()
    return response

现在鼓励您改用它:

@app.teardown_request
def after_request(exception):
    if hasattr(g, 'db'):
        g.db.close()

从好的方面来说,此更改极大地改进了内部代码流,并使自定义调度和错误处理变得更加容易。 这使得现在编写单元测试变得更加容易,因为您可以防止数据库连接关闭一段时间。 您可以利用当响应上下文从堆栈中删除时调用拆卸回调的事实,以便测试可以在请求处理后查询数据库:

with app.test_client() as client:
    resp = client.get('/')
    # g.db is still bound if there is such a thing

# and here it's gone

手动错误处理程序附加

虽然仍然可以将错误处理程序附加到 Flask.error_handlers 上,但不鼓励这样做,实际上已弃用。 一般来说,我们不再推荐自定义错误处理程序通过赋值附加到底层字典,因为更复杂的内部处理支持任意异常类和蓝图。 有关详细信息,请参阅 Flask.errorhandler()

正确的升级是改变这一点:

app.error_handlers[403] = handle_error

进入这个:

app.register_error_handler(403, handle_error)

或者,您应该只使用装饰器附加该函数:

@app.errorhandler(403)
def handle_error(e):
    ...

(注意 register_error_handler() 是 Flask 0.7 中的新内容)


蓝图支持

蓝图取代了 Flask 中先前的“模块”概念。 它们为各种功能提供了更好的语义,并在大型应用程序中更好地工作。 提供的更新脚本应该能够自动升级您的应用程序,但在某些情况下可能无法升级。 发生了什么变化?

  • 蓝图需要明确的名称。 模块有一个自动名称猜测方案,其中模块的短名称取自导入模块的最后一部分。 升级脚本尝试猜测该名称,但可能会失败,因为此信息可能会在运行时更改。
  • 蓝图对 url_for() 具有相反的行为。 之前 .foo 告诉 url_for() 它应该在应用程序上寻找端点 foo。 现在它的意思是“相对于当前模块”。 该脚本将自动为您反转对 url_for() 的所有调用。 它将以一种非常热切的方式执行此操作,因此如果您不使用模块,您最终可能会在代码中出现一些不必要的前导点。
  • 蓝图不会自动提供静态文件夹。 他们也将不再自动从其位置旁边名为 templates 的文件夹中导出模板,但是可以从构造函数中启用它。 与静态文件相同:如果您想继续提供静态文件,您需要明确地告诉构造函数静态文件夹的路径(可以相对于蓝图的模块路径)。
  • 简化了渲染模板。 现在蓝图可以提供添加到通用模板搜索路径的模板文件夹。 这意味着如果您希望 blueprintname/template.html 作为模板名称,则需要将另一个具有蓝图名称的子文件夹添加到该文件夹中。

如果继续使用已弃用的 Module 对象,Flask 会尽可能地恢复之前的行为。 但是,我们强烈建议升级到新蓝图,因为它们提供了许多有用的改进,例如多次附加蓝图的能力、蓝图特定的错误处理程序等等。


版本 0.6

Flask 0.6 带有向后不兼容的更改,这会影响请求后处理程序的顺序。 以前按注册顺序调用,现在按相反顺序调用。 进行此更改是为了使 Flask 的行为更像人们期望它的工作方式以及其他系统如何处理请求的预处理和后处理。 如果您依赖于 post-request 函数的执行顺序,请务必更改顺序。

另一个破坏向后兼容性的变化是上下文处理器将不再覆盖直接传递给模板渲染函数的值。 例如,如果 request 作为直接传递给模板的变量,则默认上下文处理器将不会使用当前请求对象覆盖它。 这使得以后更容易扩展上下文处理器以注入额外的变量,而不会破坏现有的模板而不期望它们。


版本 0.5

Flask 0.5 是第一个作为 Python 包而不是单个模块的版本。 有一些内部重构,因此如果您依赖未记录的内部细节,您可能必须调整导入。

以下更改可能与您的应用程序相关:

  • 所有模板不再发生自动转义。 相反,它被配置为仅发生在以 .html.htm.xml.xhtml 结尾的文件上。 如果你有不同扩展名的模板,你应该覆盖 select_jinja_autoescape() 方法。
  • 在此版本中,Flask 不再支持压缩应用程序。 如果需要此功能,此功能可能会在未来版本中恢复。 删除对此的支持使 Flask 内部代码更容易理解,并修复了几个使调试变得比必要更困难的小问题。
  • create_jinja_loader 功能没了。 如果您现在想自定义 Jinja 加载器,请改用 create_jinja_environment() 方法。


版本 0.4

对于应用程序开发人员,没有需要更改代码的更改。 但是,如果您正在开发 Flask 扩展,并且该扩展具有单元测试模式,您可能希望将该模式的激活链接到新的 TESTING 标志。


版本 0.3

Flask 0.3 引入了配置支持和日志记录以及闪烁消息的类别。 所有这些都是 100% 向后兼容的功能,但您可能希望利用它们。

配置支持

配置支持使得编写任何需要某种配置的应用程序变得更加容易。 (最有可能是任何应用程序的情况)。

如果您以前有这样的代码:

app.debug = DEBUG
app.secret_key = SECRET_KEY

您不再需要这样做,而只需将配置加载到配置对象中即可。 配置处理中概述了其工作原理。


日志集成

Flask 现在为您配置了一个记录器,其中包含一些基本且有用的默认值。 如果您在生产中运行您的应用程序并希望从自动错误日志中获利,您可能对附加适当的日志处理程序感兴趣。 您也可以在适当的时候开始将警告和错误记录到记录器中。 有关更多信息,请阅读 应用程序错误


快讯类别

Flash 消息现在可以附加类别。 例如,这使得以不同方式呈现错误、警告或常规消息成为可能。 这是一个选择加入的功能,因为它需要对代码进行一些重新思考。

消息闪烁 模式中阅读所有相关内容。