Flask: 应用工厂中蓝图必要吗?

17 投票
3 回答
7207 浏览
提问于 2025-04-18 16:54

我想要创建几个应用工厂(现在有一个用于开发,另一个用于测试)。我在想,怎么做才是正确的方式。

目前我使用应用对象来注册视图(通过 @app.route() 装饰器)。我需要开始使用蓝图(而不是应用对象)来注册视图吗?有没有办法在不使用蓝图的情况下,正确地创建应用工厂?

3 个回答

3

你当然可以没有蓝图就创建应用工厂,但这样通常没有意义。

假设你有一个叫做 myapp 的应用包。这里是你的 __init__.py 文件:

from flask import Flask

def create_app():
    app = Flask(__name__)

    return app

现在我们在 myapp 包外面创建一个新的 .py 文件,叫做 autoapp.py(或者 wsgi.pymanage.py 等等)。在 autoapp.py 文件中,你会创建应用实例,并从 myapp 中导入视图:

from myapp import create_app

app = create_app()

from myapp import views

这个导入语句会把 app 和你的路由连接起来。你可以在 views.py 中这样导入 app

from autoapp import app

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

应用的结构:

myapp/
    myapp/
        __init__.py
        views.py
    autoapp.py
6

对于那些在网上搜索这个问题的人,你不一定要使用蓝图。只需在你的 routes.py(或者 views.py,随便哪个)中导入 current_app 作为 app,就可以开始了。

from flask import current_app as app

另外,你还需要在工厂函数(create_app 函数)中添加这些内容,以注册你的路由:

with app.app_context():
    from . import routes
19

从技术上讲,你其实不需要蓝图(blueprints),可以直接在你的 create_app 函数里注册每一个路由。不过,通常这样做并不是个好主意,这也是蓝图存在的原因。

没有蓝图的例子

def create_app():
  app = Flask(__name__)

  @app.route('/')
  def index():
    return render_template('index.html')

  return app

如果你配置得当,可以有一个单一的应用工厂,既可以用于测试,也可以用于其他用途。如果你想根据是否在测试中加载不同的蓝图,可以这样做。

from project.config import configurations as c

def create_app(config=None):
  " make the app "
  app = Flask(__name__)
  app.config.from_object(c.get(config, None) or c['default'])

  configure_blueprints(app)

  return app

def configure_blueprints(app):
  " register the blueprints on your app "
  if app.testing:
    from project.test_bp import bp
    app.register_blueprint(bp)
  else:
    from project.not_test_bp import bp
    app.register_blueprint(bp)

然后 project/config.py 可以像这样:

class DefaultConfig(object):
  PROJECT_NAME = 'my project'

class TestingConfig(DefaultConfig):
  TESTING = True

class DevConfig(DefaultConfig):
  DEBUG = True

configurations = {
  'testing': TestingConfig,
  'dev': DevConfig,
  'default': DefaultConfig
}

为每个蓝图创建一个文件夹,文件夹里的 __init__.py 文件用来实例化这个蓝图。假设有一个叫 routes 的蓝图。

from flask import Blueprint

bp = Blueprint('routes', __name__)

from project.routes import views

那么在 project/routes/views.py 中,你可以放置你的视图。

from project.routes import bp

@bp.route('/')
def index():
  return render_template('routes/index.html')

撰写回答