将大型应用作为包组织

想象一个简单的 Flask 应用结构如下:

/yourapplication
    yourapplication.py
    /static
        style.css
    /templates
        layout.html
        index.html
        login.html
        ...

虽然这对于小型应用来说已经足够,但对于更大的应用,建议使用包而不是模块。教程 教程使用的是包结构,请参见 示例代码

简单的包结构

要将其转换为一个更大的结构,只需在现有目录中创建一个新的文件夹 yourapplication,并将所有内容移入其中。然后将 yourapplication.py 重命名为 __init__.py。(请确保先删除所有 .pyc 文件,否则很可能会出错)

此时,你应该得到类似以下的结构:

/yourapplication
    /yourapplication
        __init__.py
        /static
            style.css
        /templates
            layout.html
            index.html
            login.html
            ...

但现在该如何运行你的应用呢?直接运行 python yourapplication/__init__.py 是行不通的。简单来说,Python 不允许包中的模块作为启动文件。但这并不是大问题,只需在内层 yourapplication 文件夹旁边添加一个名为 pyproject.toml 的新文件,内容如下:

[project]
name = "yourapplication"
dependencies = [
    "flask",
]

[build-system]
requires = ["flit_core<4"]
build-backend = "flit_core.buildapi"

安装你的应用,使其可以被导入:

$ pip install -e .

要使用 flask 命令运行你的应用,需要设置 --app 选项来告诉 Flask 去哪里寻找应用实例:

$ flask --app yourapplication run

这样做有什么好处?现在我们可以将应用重新组织为多个模块。只需要记住以下几点:

  1. Flask 应用对象的创建必须在 __init__.py 文件中。这样每个模块都可以安全地导入它,并且 __name__ 变量会解析为正确的包。

  2. 所有的视图函数(那些带有 route() 装饰器的函数)必须在 __init__.py 文件中导入。不是导入函数本身,而是导入它所在的模块。**在创建应用对象之后**再导入视图模块。

这是一个示例 __init__.py:

from flask import Flask
app = Flask(__name__)

import yourapplication.views

然后这是 views.py 的内容:

from yourapplication import app

@app.route('/')
def index():
    return 'Hello World!'

此时,你应该得到类似以下的结构:

/yourapplication
    pyproject.toml
    /yourapplication
        __init__.py
        views.py
        /static
            style.css
        /templates
            layout.html
            index.html
            login.html
            ...

循环导入

每个 Python 程序员都讨厌循环导入,但我们刚刚引入了它们:循环导入(即两个模块互相依赖。本例中 views.py 依赖 __init__.py)。通常这是个坏主意,但在这里其实没问题。原因是我们并没有在 __init__.py 中真正使用视图,只是确保模块被导入,而且我们是在文件底部导入的。

使用蓝图

如果你的应用较大,推荐将其划分为多个小模块,每个模块使用蓝图实现。有关该主题的入门介绍,请参阅文档中的 使用蓝图模块化应用 章节。