将Flask应用拆分成多个文件

7

我正在尝试使用Flask。我的目录结构如下:

|--------flask-test
|----------------app
|-----------------------static
|-----------------------templates
|-----------------------venv
|-----------------------__init__.py

venv文件夹保存了我的虚拟flask安装。我的__init__.py文件如下:

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
    return "Hello World!"
if __name__ == "__main__":
    app.run()

这段代码目前没有问题,但是现在我想把它拆分成两个文件__init__.pymain.pymain.py应该与__init__.py在同一个目录下。到目前为止,我尝试过以下方法: __init__.py:
from flask import Flask

app = Flask(__name__)
import main

main.py:

from app import app
@app.route("/")
    def hello():
        return "Hello World!"

然而,在尝试运行 __init__.py 时,我遇到了一个错误,指出模块 appmain.py 中不存在。我在这里做错了什么?还有,我应该把运行方法放在哪里?


你有一个循环导入问题... 你不能在__init__中导入main。并且在建立路由之后,将运行方法放在main中。 - OneCricketeer
2个回答

24

使用Flask蓝图,您可以将应用程序拆分为多个文件,然后将它们合并成一个更大的应用程序。

以下是一个示例应用程序,拆分为3个文件,演示了这一点:

  • file1: 定义一个/hello路由
  • file2: 定义一个/world路由
  • file3: 主应用程序,通过使用register_blueprint函数将file1和file2中的应用程序集成起来,充当粘合剂

file1: 使用路由/hello定义app_file1。

from flask import Blueprint, render_template, session,abort

app_file1 = Blueprint('app_file1',__name__)
@app_file1.route("/hello")
def hello():
    return "Hello World from app 1!"

file2:定义了一个名为app_file2的应用程序,其路由为/world。

from flask import Blueprint, render_template, session,abort

app_file2 = Blueprint('app_file2',__name__)
@app_file2.route("/world")
def world():
    return "Hello World from app 2!"

文件3:主应用程序

from flask import Flask
from file1 import app_file1
from file2 import app_file2
main_app = Flask(__name__)
main_app.register_blueprint(app_file1)
main_app.register_blueprint(app_file2)

注意: 为了简化事情,本示例中的文件都放在一个目录中。在更大的应用程序中,您会希望进一步将它们分成目录/模块。使用模块是额外的步骤,可以使您仅公开您想要公开的功能,执行额外的初始化并避免循环依赖。

还有一个好习惯是为诸如数据访问(如SQLAlchemy模型)之类的内容添加其他文件夹。将具有共同功能的文件(例如支付处理)封装到模块中以供潜在重用、代码清晰度和维护性。

如果您的应用程序有大量视图,您可能还需要添加其他子文件夹。


1
为什么file1和file2都使用参数app_classifieds,它们应该不同吗?文件3是否是__init__.py?另外,run方法在哪里? - KexAri
因为我是从一个现有的应用程序中复制粘贴的,所以你是正确的。我会修正答案。 - Youn Elan
1
文件3可以是__init__.py或任何您想要的名称。它是将多个文件中的所有应用程序合并为单个应用程序的代码。原则是相同的。 - Youn Elan
这个很好用。你还需要在file3底部加上app.run()。你认为这比http://flask.pocoo.org/docs/0.11/patterns/packages/的方法更好吗?我发的链接使用了一个独立于主应用程序文件夹之外的脚本,类似于`run.py`。 - KexAri
1
方法并不互相矛盾。包的最大优点是,如果存在循环导入,它们可以放在__init__文件中,但如果没有这种情况,那么它并不重要。我认为这取决于您的应用程序有多大以及来自多个文件的代码有多少相互关联...对于3个自包含文件,请将它们全部放在一个目录中。 - Youn Elan

2

我稍微修改了这个例子,但是只想尽可能地保持简单。结构看起来像这样:

app/
  __init__.py # empty this time
  main.py
  run.py

在运行时,您需要初始化应用程序并从主文件加载路由,将app.run放入__name__ == '__main__'中即可实现 - 因为所有代码都会在此之前执行。
# in run.py
from flask import Flask
app = Flask(__name__)
from main import *


if __name__ == '__main__':
    print app.url_map
    app.run(debug=True)

在启动应用程序之前,在main.py中指定您的路由,并从中导入。

# in main.py
from run import app

@app.route("/")
def hello():
    return "Hello World!"

获取错误文件 "init.py",第4行,模块 <module> 中 from app import main 导入错误:没有名为 app 的模块。 - KexAri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接