升级到新版本

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,你可能会看到一些意想不到的变化。

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

调试

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

错误处理

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

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

注意

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

模板

默认情况下,render_template_string()函数已更改为autoescape模板变量。这更好地匹配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

从函数返回元组的行为被简化。如果你返回一个元组,它不再定义你创建的响应对象的参数,它现在总是一个tuple形式(响应, 状态, 标头)其中必须提供至少一个项目。如果你依赖于旧的行为,你可以很容易地通过继承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例如,app上下文栈对连接到数据库的扩展有意义。使用应用程序上下文堆栈而不是请求上下文堆栈将使扩展更容易处理请求之外的用例。

版本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作为版本控制系统,建议使用路径 -p1 < patchfile.diff,然后使用交互式提交功能仅应用看起来不错的块。

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

  1. 下载脚本:flask07-upgrade.py

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

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

  4. 应用补丁:

    patch -p1 < patchfile.diff
    
  5. 如果您使用的是每个模块的模板文件夹,您需要移动一些模板。以前,如果在名为admin的蓝图旁边有一个名为templates的文件夹,模板文件的隐式模板路径自动为admin/index.html称为templates/index.html这不再是这样。现在,您需要将模板命名为templates/admin/index.html该工具不会检测到这个,所以你必须自己这样做。

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

如果您使用Windows并且缺少patch命令行实用程序,您可以将其作为Windows的各种Unix运行时环境(包括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的行为更像人们期望它工作,以及其他系统如何处理请求预处理和后处理。如果依赖于后请求函数的执行顺序,请务必更改顺序。

破坏向后兼容性的另一个变化是上下文处理器将不再覆盖直接传递给模板呈现函数的值。如果例如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

你不再需要这样做,而只需将配置加载到配置对象。此工作原理在Configuration Handling中概述。

日志集成

Flask现在用一些基本和有用的默认值配置一个logger。如果您在生产环境中运行应用程序并希望从自动错误日志记录中获益,您可能有兴趣附加一个正确的日志处理程序。此外,您还可以在适当时开始将记录和警告记录到记录器中。有关详细信息,请参阅Application Errors

Flash消息类别

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

请阅读Message Flashing模式中的所有内容。