如何将任意参数传递给烧瓶蓝图?

How to pass arbitrary arguments to a flask blueprint?

我有一个烧瓶 api,我用一个物体包裹了它。这样做使单元测试变得轻而易举,因为我可以使用各种不同的设置实例化 api,具体取决于它是在生产中、测试中还是在其他方面。

我现在正在尝试稍微扩展 api,为此我正在使用蓝图。问题是我不知道如何将参数传递给蓝图。我的路线需要访问哪个数据库等信息,并且该信息不是静态的。如何将此信息传递到蓝图中?我以下面的代码为例:

api.py:

class MyApi(object):
    def __init__(self, databaseURI):
     self.app = Flask(__name__)
     self.app.register_blueprint(myblueprint)

blueprint.py

myblueprint= Blueprint('myblueprint', __name__)
@myblueprint.route('/route', methods=['GET'])
def route():
  database = OpenDatabaseConnection(databaseURI)

这里有一个相关的问题: How do I pass constructor arguments to a Flask Blueprint?

但是回答问题的人解决了 op 的用例特定问题而没有实际回答如何将任意参数传递给蓝图的问题。

您可以在构造函数中动态创建蓝图:

def construct_blueprint(database):

    myblueprint = Blueprint('myblueprint', __name__)

    @myblueprint.route('/route', methods=['GET'])
    def route():
        database = database

    return(myblueprint)

这样就可以在 appfactory 中添加蓝图,传递参数。有时您会需要它,而烧瓶文档中的任何地方都没有描述它。

假设 bp1.py、bp2.py 与您的 appname

在同一文件夹中
from appname import bp1, bp2

app.register_blueprint(bp1.bp)
# with parameters:
app.register_blueprint(bp2.construct_blueprint(arg1, arg2))

里面 bp2.py:

def construct_blueprint(arg1, arg2):
    bp = Blueprint("bp2", __name__)

    @bp.route('/test')
    def test():
        ret = {'arg1': arg1, 'arg2': arg2}
        return jsonify(ret)

    return bp

使用 Flask config system (app.config) to store all your config data, then from your Blueprint read your Application Context 使用 current_app

存储在app.config:

app.config[DATABASE_URI] = databaseURI

读取应用上下文:

databaseURI = current_app.config[DATABASE_URI]

示例代码

main.py

from flask import Flask
from blueprint import myblueprint

app = Flask(__name__)
app.register_blueprint(myblueprint)
app.config[DATABASE_URI] = databaseURI

blueprint.py

from flask import current_app

myblueprint= Blueprint('myblueprint', __name__)
@myblueprint.route('/route', methods=['GET'])
def route():
  databaseURI = current_app.config[DATABASE_URI]
  database = OpenDatabaseConnection(databaseURI)

我通过在辅助蓝图 python 文件中创建一个 class 来以稍微不同的方式解决这个问题。这样我就可以调用一次加载 class,然后将结果传递给主 python 脚本中的蓝图函数。当我加载 class 时,我可以传递我配置的任何属性。我喜欢这种方法,因为它使我的代码更加简洁。

如果您想下载我放在这里的代码,也可以在 https://github.com/dacoburn/example-flask-blueprints 找到。我在 github 中添加了评论,其中包含有关 python 文件中发生的事情的更多详细信息。

我的文件夹结构是: 来源 |___main.py |___routes |___index.py |___example.py |___templates |___index.html |___example.html

main.py

from flask import Flask
import os
from routes.index import Index
from routes.example import Example

app = Flask(__name__)
index = Index("Example User")
example = Example("Random Arg")
app.register_blueprint(index.index)
app.register_blueprint(example.example)

if __name__ == '__main__':
    port = int(os.environ.get('APP_PORT', 5000))
    app.run(host='0.0.0.0', port=port, debug=True)

index.py

from flask import render_template, Blueprint


class Index:

    def __init__(self, username):
        self.username = username
        self.index = self.create_index()

    def create_index(self):
        index_page = Blueprint("index", __name__)

        @index_page.route("/", methods=['GET'])
        def index():
            return render_template("index.html", username=self.username)

        return index_page

example.py

from flask import render_template, Blueprint


class Example:

    def __init__(self, arg):
        self.arg = arg
        self.example = self.create_example()

    def create_example(self):
        example_page = Blueprint("example", __name__)

        @example_page.route("/<username>", methods=['GET'])
        def example(username):
            return render_template("example.html",
                                   username=username,
                                   arg=self.arg)

        return example_page

index.html

<html>
    <head>
        <title>Example Page</title>
    </head>
    <body>
    <p>Hello {{ username }}</p>
    <br>
    This page also has a redirect to another route:
    <ul>
        <li><a href="/{{ username }}">Example Page</a></li>
    </ul>
    </body>
</html>

example.html

<html>
    <head>
        <title>Example Page 2</title>
    </head>
    <body>
    <p>Hello {{ username }}</p>
    <br>
    Here is the random argument: {{ arg }}
    <br>
    <br>
    This page also has a link to the main page:
    <ul>
        <li><a href="{{ url_for('index.index') }}">Index Page</a></li>
    </ul>
    </body>
</html>