Nested Blueprints in Flask?

后端 未结 3 1123
囚心锁ツ
囚心锁ツ 2020-12-09 17:54

I\'m still new to Flask, so there may be an obvious way to accomplish this, but I haven\'t been able to figure it out so far from the documentation. My app is divided into s

相关标签:
3条回答
  • 2020-12-09 18:23

    Unfortunately, nested blueprints are not a current feature in Flask. You'll have to do it manually. You could probably code something that works for your specific case, but a general solution has not been added to Flask. There has been some discussion on the issue tracker:

    • https://github.com/mitsuhiko/flask/issues/593
    • https://github.com/mitsuhiko/flask/issues/1548
    • https://github.com/pallets/flask/issues/3215

    Adding nestable blueprints into Flask is not as trivial as automatically appending a prefix to routes. There are many other features of blueprints that need to be considered when nesting that make a general implementation significantly more complicated. The reason this has not been implemented yet is that no one in the community has had a great enough need for it that wasn't solved by a quick workaround vs contributing a general implementation.

    0 讨论(0)
  • 2020-12-09 18:36

    Here is my workaround:

    When importing a blueprint, I define my nested routes:

    app.register_blueprint(product_endpoints, url_prefix='/sites/<int:site_id>/menus/<int:menu_id>/categories/<int:category_id>/products/<int:product_id>')
    app.register_blueprint(category_endpoints, url_prefix='/sites/<int:site_id>/menus/<int:menu_id>/categories/<int:category_id>')
    app.register_blueprint(menu_endpoints, url_prefix='/sites/<int:site_id>/menus/<int:menu_id>')
    app.register_blueprint(site_endpoints, url_prefix='/sites/<int:site_id>')
    

    And inside the blueprints, I'm reusing route parse functions. For example, in the product_endpoints file:

    from category_endpoints import get_category_data
    
    product_endpoints = Blueprint('product_endpoints', __name__)
    
    @product_endpoints.url_value_preprocessor
    def get_product_data(endpoint, values):
        if 'category_id' in values:
            get_category_data(endpoint, values)
    
        product = Product.get_by_id(int(values.pop('product_id')))
    
        if not product:
            abort(404)
    
        g.product = product
    

    and in category_endpoints file:

    from menu_endpoints import get_menu_data
    
    category_endpoints = Blueprint('category_endpoints', __name__)
    
    @category_endpoints.url_value_preprocessor
    def get_category_data(endpoint, values):
        if 'menu_id' in values:
            get_menu_data(endpoint, values)
        category = ProductCategory.get_by_id(int(values.pop('category_id')))
    
        if not category:
            abort(404)
    
        g.category = category
    

    etc... With that approach, my blueprint is also usable with direct routes like /products/<int:product_id>.

    This approach worked for me very well. I hope it can also help you.

    0 讨论(0)
  • 2020-12-09 18:48

    I made a class called NestedBlueprint to hack it.

    class NestedBlueprint(object):
        def __init__(self, blueprint, prefix):
            super(NestedBlueprint, self).__init__()
            self.blueprint = blueprint
            self.prefix = '/' + prefix
    
        def route(self, rule, **options):
            rule = self.prefix + rule
            return self.blueprint.route(rule, **options)
    

    Here is my base file which contains the blueprint: panel/__init__.py

    from flask import Blueprint
    
    panel_blueprint = Blueprint(PREFIX, __name__, url_prefix='/panel')
    
    from . import customize
    

    Here is the specific/nested file which contains nested blueprint: panel/customize.py

    from rest.api.panel import panel_blueprint
    from rest.api.util.nested_blueprint import NestedBlueprint
    
    nested_blueprint = NestedBlueprint(panel_blueprint, 'customize')
    
    
    @nested_blueprint.route('/test', methods=['GET'])
    def test():
        return ':)'
    

    You can then call like this:

    $ curl http://localhost:5000/panel/customize/test
    :)
    
    0 讨论(0)
提交回复
热议问题