【问题标题】:How to pass arbitrary arguments to a flask blueprint?如何将任意参数传递给烧瓶蓝图?
【发布时间】:2015-04-22 18:53:41
【问题描述】:

我有一个封装在一个对象中的烧瓶 api。这样做使单元测试变得轻而易举,因为我可以使用各种不同的设置来实例化 api,具体取决于它是在生产、测试​​还是你有的东西。

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

api.py:

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

蓝图.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?

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

【问题讨论】:

    标签: python oop flask arguments blueprint


    【解决方案1】:

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

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

    【讨论】:

    • 好主意!我当然很感激。这里的问题是我想使用蓝图的部分原因是为了组织。我真的不想要一个数千行长的 python 文件。我想将蓝图拆分成各自的文件。据我所知,不可能在 python 中跨多个文件传播类定义。我意识到我可以创建一个“扩展”类链,但这似乎有点骇人听闻。
    • 是什么阻止您将该功能放入模块中然后使用它myblueprint = module.construct_blueprint(database)
    • 只有我一天结束的疲倦。谢谢先生。
    【解决方案2】:

    使用Flask config system (app.config) 存储您的所有配置数据,然后从您的蓝图中使用current_app 读取您的Application Context

    存储在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
    

    蓝图.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)
    

    【讨论】:

      【解决方案3】:

      通过这种方式,可以在 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
      

      【讨论】:

        【解决方案4】:

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

        我在这里输入的代码也可以在https://github.com/dacoburn/example-flask-blueprints找到,如果你想下载的话。我将 cmets 添加到 github,其中包含有关 python 文件中发生的更多详细信息。

        我的文件夹结构是: 源代码 |___main.py |___路线 |___索引.py |___示例.py |___模板 |___索引.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>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-21
          • 2013-12-05
          • 1970-01-01
          • 2016-04-13
          • 2021-02-28
          • 1970-01-01
          • 2021-02-08
          • 2023-03-09
          相关资源
          最近更新 更多