升级到新版本

Flask本身的变化就像任何软件随着时间的推移而不断地更新自己。大多数更改都是很好的类型,在这种情况下,您不需要更改代码中的任何内容就可以应用新版本的 Flask。

不过,每当 Flask 有更新时,我们都建议你适当地修改自己的代码,以充分地利用这些新功能,提高自己代码地质量。

本章节文档为您列举了 Flask 各版本之间地差异,以及你如何修改自身代码才能更好地升级。

通过提供 --upgrade 参数,使用 pip 命令去升级你现在的Flask:

$ pip install --upgrade Flask

版本0.12

发送文件的更改

这个 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

Flask0.11版本不具有任何特色,因为它本身应该是1.0版本。然而,由于发布之前的周期太长,我们决定先推出0.11版本,并删除一些更改,以使转换更容易。如果您一直在跟踪主分支1.0,您可能会看到一些意外的更改。

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

调试

Flask 0.11版本从应用程序 移除了``debug_log_format`` 的属性。取而代之的是新的 LOGGER_HANDLER_POLICY,这个配置可用于禁用默认日志处理程序,并且可以设置自定义日志处理程序。

错误处理

错误处理程序的行为已更改。在过去,处理程序的优先是分别基于的修饰/调用顺序 errorhandler()register_error_handler() 。现在继承层次结构优先,执行更具体的异常类的处理程序,而不是更一般的异常类。关于这个问题,请参阅 错误处理

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

注解

过去,仅允许你为异常的实例注册处理器,这是一个无意的逻辑上的绝对错误,因此替换为只使用异常类和HTTP错误代码注册处理程序的预期行为。

模板法

这个模板线性函数已更改为自动转义模板变量。这更符合渲染模板的操作。

扩展导入

flask.ext.foo``形式的扩展导入 已弃用,应使用 ``flask_foo .

旧的形式仍然有效,但对于旧模式下导入的扩展,Flask即将重新发布 flask.exthook.ExtDeprecationWarning。此外,我们还提供一个名为 flask-ext-migrate 这应该会自动重写你的导入。

版本0.10

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

为了避免破坏用户的 session 数据,你可以使用 Flask 扩展 Flask-OldSessions 来代替原先的 session。

Flask也开始储存应用情境而不是请求情境下的 g 对象。这种变化应该是透明的,但它意味着你现在可以在没有请求情境下但是必须要有应用情境下储存在``g`` 对象。旧的``flask.Flask.request_globals_class`` 属性已重命名为 flask.Flask.app_ctx_globals_class .

版本0.9

从函数中返回元组的操作被简化了,返回元组时你不再需要为你创建的 response 对象定义参数了,现在它始终是 ``(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,但仍须检查是否可行。例如,应用程序情境存储对于连接到数据库的扩展是有意义的,在请求无关的用例中使用它比 request stack 处理起来更容易。

版本0.8

Flask引入了一个新的会话接口系统。我们还注意到,在实现会话的 flask.session 模块和全局会话对象的 flask.session 之间存在冲突。在介绍之后,我们将会话系统的实现细节转移到一个名为:mod: ' flask.sessions '的新模块中。如果您使用了以前没有文档说明的会话支持,我们强烈建议您升级。

如果提交了无效的JSON数据,那么flask就会出现 BadRequest 的异常,而不是让默认 ValueError 出现。这样做的好处是,您不再需要处理该错误,以避免为用户显示内部服务器错误。如果您在过去显式地将其捕获为:exc: ' ValueError ',那么您将需要更改它。

由于测试客户端Flask0.7中的一个bug,当测试客户端在with语句中使用时,没有触发拆卸处理程序。这是固定的,但如果您依赖于此行为,可能需要在您的测试套件中进行一些更改。

版本0.7

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

该脚本扫描整个应用程序,并生成一个统一的diff,其中假定可以安全地应用更改。然而,由于这是一个自动化工具,它将无法找到所有用例,并且可能会遗漏一些用例。我们在内部将大量的拒绝警告散布到各处,以便于找到无法升级的代码片段。

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

如果您在项目中使用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”的蓝图旁边有一个名为:file: ' templates '的文件夹,那么隐式模板路径将自动为:file: ' admin/index。用于一个名为:file: ' templates/index.html '的模板文件。现在情况已经不同了。现在需要将模板命名为:file: ' templates/admin/index.html '。该工具不会检测到这一点,所以您将不得不自己做这件事。

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

如果您正在使用windows,并且缺少“补丁”命令行实用程序,您可以将其作为windows的各种Unix运行时环境的一部分,包括cygwin、msysgit或ming32。此外,像svn、hg或git这样的源代码控制系统也内置了对应用该工具生成的统一差异的支持。有关更多信息,请参阅版本控制系统的手册。

请求局部变量中的错误

由于早期实现中的一个bug,当请求本地代理被解除绑定时,它会抛出一个:exc: ' RuntimeError ',而不是一个:exc: ' AttributeError '。如果您以前使用:exc: ' AttributeError '捕获这些异常,那么现在应该使用:exc: ' RuntimeError '捕获它们。

另外, send_file() 如果您依赖将在Flask0.11中移除的功能,那么函数现在将发出折旧警告。以前在传递文件对象时可以使用etags和mimetype。这是不可靠的,导致了一些设置的问题。如果收到拒绝警告,请确保更新应用程序以使用其中的文件名,或者禁用etag附加并自己附加它们。

旧代码:

return send_file(my_file_object)
return send_file(my_file_object)

新代码:

return send_file(my_file_object, add_etags=False)

升级到新的Teardown处理

我们简化了请求处理回调的行为。对于修改响应的内容, 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()。以前' '。告诉:meth: ' url_for ',它应该在应用程序上查找端点' ' foo ' '。现在它的意思是“相对于当前模块”。脚本将自动为您反转对:meth: ' url_for '的所有调用。它将以一种非常迫切的方式完成这一任务,因此如果不使用模块,代码中可能会出现一些不必要的前导点。
  • 蓝图不会自动提供静态文件夹。它们也不再自动从名为 templates 但它可以从构造函数中启用。与静态文件相同:如果要继续提供静态文件,则需要显式地告诉构造函数静态文件夹的路径(可以相对于蓝图的模块路径)。
  • 简化了呈现模板。现在,蓝图可以提供添加到通用模板搜索路径的模板文件夹。这意味着,如果您想要:file: ' blueprintname/template,则需要将另一个带有blueprint名称的子文件夹添加到该文件夹中。html '作为模板名称。

如果您继续使用 Module 对象,如果不推荐使用该对象,则flask将尽可能恢复以前的行为。但是,我们强烈建议升级到新的蓝图,因为它们提供了许多有用的改进,例如多次附加蓝图的能力、特定于蓝图的错误处理程序等等。

版本0.6

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

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

版本0.5

Flask 0.5是第一个发布版,它是以python包而不是单个模块的形式提供的。有一些内部重构,因此如果您依赖于未记录的内部细节,那么您可能需要调整导入。

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

  • 自动转义不再适用于所有模板。相反,它被配置为只在以 .html.htm.xml.xhtml . 如果模板具有不同的扩展名,则应重写 select_jinja_autoescape() 方法。
  • 在这个版本中,flask不再支持压缩应用程序。如果需要此功能,此功能可能会在将来的版本中恢复。删除对这一点的支持可以使flask内部代码更容易理解,并修复一些小问题,使调试变得比必要的更困难。
  • 没有这个' ' create_jinja_loader ' '函数。如果您现在想自定义Jinja加载程序,请使用:meth: ' ~flask.Flask。create_jinja_environment相反的方法。

版本0.4

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

版本0.3

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

配置支持

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

如果以前有这样的代码:

app.debug = DEBUG
app.secret_key = SECRET_KEY

您不再需要这样做,而是可以将配置加载到配置对象中。工作原理概述见 配置管理 .

日志记录集成

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

闪光信息类别

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

请阅读 信息闪烁 模式。