Flask 扩展开发

    如果你需要创建自己的扩展,那么本文可以帮助你让扩展立马上线运行。

    扩展都放在一个名如 的包中。其中的“ something ”就是扩展所要连接的库的名称。例如假设你要为 Flask 添加 _simplexml 库的支持,那么扩展的包名称就应该是 flask_simplexml

    但是,真正扩展的名称(可读名称)应当形如“ Flask-SimpleXML ”。请确保名称中包含“ Flask ”,并且注意大小写。这样用户就可以在他们的 setup.py文件中注册依赖。

    但是扩展具体是怎么样的呢?一个扩展必须保证可以同时在多个 Flask 应用中工作。这是必要条件,因为许多人为了进行单元测试,会使用类似 应用工厂模式来创建应用并且需要支持多套配置。因此,你的应用支持这种行为非常重要。

    最重要的是,扩展必须与一个 setup.py 文件一起分发,并且在 PyPI 上注册。同时,用于开发的检出链接也应该能工作,以便于在 virtualenv 中安装开发版本,而不是手动下载库。

    Flask 扩展必须使用 BSD 或 MIT 或更自由的许可证来许可,这样才能被添加进Flask 扩展注册表。请记住, Flask 扩展注册表是比较稳健的,并且扩展在发布前会进行预审是否符合要求。

    “ Hello Flaskext! ”

    好吧,让我们开展创建一个 Flask 扩展。这个扩展的用途是提供最基本的 SQLite3支持。

    首先创建如下结构的文件夹和文件:

    以下是最重要的文件及其内容:

    接下来 setup.py 是必需的,该文件用于安装你的 Flask 扩展。文件内容如下:

    1. """
    2. Flask-SQLite3
    3. -------------
    4. This is the description for that library
    5. """
    6. from setuptools import setup
    7. setup(
    8. name='Flask-SQLite3',
    9. version='1.0',
    10. url='http://example.com/flask-sqlite3/',
    11. license='BSD',
    12. author_email='your-email@example.com',
    13. description='Very short description',
    14. long_description=__doc__,
    15. py_modules=['flask_sqlite3'],
    16. # if you would be using a package instead use packages instead
    17. # of py_modules:
    18. # packages=['flask_sqlite3'],
    19. zip_safe=False,
    20. platforms='any',
    21. install_requires=[
    22. 'Flask'
    23. ],
    24. classifiers=[
    25. 'Environment :: Web Environment',
    26. 'Intended Audience :: Developers',
    27. 'License :: OSI Approved :: BSD License',
    28. 'Operating System :: OS Independent',
    29. 'Programming Language :: Python',
    30. 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
    31. 'Topic :: Software Development :: Libraries :: Python Modules'
    32. ]
    33. )

    代码相当多,但是你可以从现有的扩展中直接复制/粘贴,并修改相应的内容。

    flask_sqlite3.py

    这个文件是你的扩展的具体实现。但是一个扩展到底是怎么样的?最佳实践是什么?继续阅读吧。

    许多扩展会需要某种类型的初始化步骤。例如,假设一个应用像文档中建议的一样( )正在连接到 SQLite 。那么,扩展如何获知应用对象的名称?

    相当简单:你把名称传递给扩展。

    推荐两种初始化扩展的方式:

    初始化函数:

    使用哪种方式取决于你。对于 SQLite 3 扩展,我们会使用基于类的方式,因为这样可以提供给用户一个用于打开和关闭数据库连接的对象。

    当设计类时,重要的一点是使用它们在模块层易于复用。也就是说,对象本身在任何情况下不应存储任何应用的特定状态,而必须可以在不同的应用之间共享。

    扩展的代码

    以下是 flask_sqlite3.py 的内容,可以复制/粘贴:

    那么这是这些代码的含义是什么:

    • init_app 方法使得 SQLite3 对象不需要应用对象就可以实例化。这个方法支持工厂模式来创建应用。 init_app 会配置数据库。如果不提供配置,默认配置为内存数据库。此外, init_app 方法附加了 teardown处理器。

    • 接下来,我们定义了 connect 方法来打开一个数据库连接。

    • 最后,我们添加一个 connection 属性,首次访问时打开数据库连接,并把它存储在环境中。这也是处理资源的推荐方式:在资源第一次使用时获取资源,即惰性获取。

    注意这里,我们把数据库连接通过 _app_ctx_stack.top 附加到应用环境的栈顶。扩展应该使用上下文的栈顶来存储它们自己的信息,并使用足够复杂的名称。

    那么为什么我们决定在此使用基于类的方法?因为我们的扩展是这样使用的:

    1. from flask import Flask
    2. from flask_sqlite3 import SQLite3
    3. app = Flask(__name__)
    4. app.config.from_pyfile('the-config.cfg')
    5. db = SQLite3(app)

    你可以在视图中这样使用数据库:

    同样,如果在请求之外,可以通过压入应用情境的方法使用数据库:

    1. with app.app_context():
    2. cur = db.connection.cursor()
    3. cur.execute(...)

    with 块的末尾,拆卸处理器会自动执行。

    另外, init_app 方法用于在创建应用时支持工厂模式:

    记住已审核的 Flask 扩展必须支持用工厂模式来创建应用(下面会解释)。

    init_app 的注意事项

    当扩展需要找到当前应用,且没有一个指向当前应用的引用时,必须使用 环境局部变量或用一种你可以显式传递应用的方法更改 API 。

    在上面的例子中,在每个请求之前,一个 sqlite3db 变量被分配到_app_ctx_stack.top 。在一个视图函数中,这个变量可以使用 SQLite3的属性 connection 来访问。在请求解散时, sqlite3_db 连接被关闭。通过使用这个模式,在请求持续的期间,可以访问 相同_ 的 sqlite3 数据库连接。

    学习借鉴

    本文只是谈了一些扩展开发的皮毛。如果想要深入,那么查看 上已有的扩展是明智的。如果你感到迷失,还可以通过 邮件列表 和 学习到优秀的 APIs 。尤其当你要开发一个全新的扩展时,建议先多看多问多听,这样不仅可以知道别人的需求,同时也避免闭门造车。

    谨记:设计优秀的 API 是艰难的。因此请先在邮件列表里介绍你的项目,让其他开发者在 API 设计上助你一臂之力。

    最好的 Flask 扩展是那些共享 API 智慧的扩展,因此越早共享越有效。

    Flask 有已审核的扩展的概念。已审核的扩展会被视作 Flask 的一部分来测试,以保证扩展在新版本发布时不会出问题。这些已审核的扩展会在 Flask 扩展注册表中列出,并有相应的标记。如果你想要自己的扩展通过审核,请遵循以下的指导方针:

    • 一个已审核的 Flask 扩展需要一个维护者。如果一个扩展作者想要放弃项目,那么项目应该寻找一个新的维护者,包括移交完整的源码托管和 PyPI 访问。如果找不到新的维护者,请赋予 Flask 核心团队访问权限。

    • 一个已审核的 Flask 扩展必须提供一个名如 flask_extensionname 的包或模块。

    • 它必须带有测试套件,套件可以使用 make test 或者python setup.py test 来调用。如果是使用 make test 调用的测试套件,那么必须保证所有的依赖可以自动安装。如果是使用 python setup.pytest 调用的测试套件,那么测试的依赖可以在 setup.py 文件中定义。测试套件分发的必要组成部分。

    • 已审核的扩展的 API 可以通过下面特性的检查:

    • 许可协议必须是 BSD/MIT/WTFPL 协议。

    • 官方扩展的命名模式是 Flask-ExtensionNameExtensionName-Flask

    • 已审核的扩展必须在 setup.py 文件里定义所有的依赖关系,除非在PyPI 上不可用。

    • 扩展的文档必须使用来自 的 flask 主题。

    • setup.py 描述(即 PyPI 描述)必须链接到文档、网站(如果有的话),并且必须有自动安装开发版本的链接( PackageName==dev )。

    • 现行扩展必须支持 Python 2.7 和 Python 3.4 (及以后版本)。