Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwrite route in flask blueprint

Tags:

There is a blueprint with a lot of useful routes defined, but I have no control over it (can not change it's code in any way) Trying to reuse it in a different app but one of the blueprint's endpoints must be overloaded. How can I achieve that?

I tried just adding a new route to blueprint on top of the existing one:

@blueprint.route('/my/route', methods=['PUT', 'POST'])
def my_new_view_func(program, project):
    # some new behavior for the endpoint

As the result there is duplicate url_rule in app.url_map.iter_rules():

<Rule '/my/route' (PUT, POST) -> my_view_func>,
<Rule '/my/route' (PUT, POST) -> my_new_view_func>,

and when requesting /my/route old viewer my_view_func gets executed

Can I somehow get rid of the old url rule? Or maybe there is a better way to overwrite the route?

like image 258
MaxPY Avatar asked Apr 11 '18 21:04

MaxPY


People also ask

How do you pass parameters on a Flask route?

flask route params Parameters can be used when creating routes. A parameter can be a string (text) like this: /product/cookie . So you can pass parameters to your Flask route, can you pass numbers? The example here creates the route /sale/<transaction_id> , where transaction_id is a number.

How do you use blueprints in Flask?

To use any Flask Blueprint, you have to import it and then register it in the application using register_blueprint() . When a Flask Blueprint is registered, the application is extended with its contents. While the application is running, go to http://localhost:5000 using your web browser.

What is the default route request in Flask?

By default, a route only answers to GET requests. You can use the methods argument of the route() decorator to handle different HTTP methods. If GET is present, Flask automatically adds support for the HEAD method and handles HEAD requests according to the HTTP RFC.

Can you use multiple decorators to route URLs to a function in Flask?

We can use multiple decorators by stacking them.


1 Answers

There are 2 solutions which I found. First:

from flask import Flask, Blueprint


simple_page = Blueprint('simple_page', __name__, )


@simple_page.route('/my/route/')
def my():
    # for example it's a registered route somewhere...
    return 'default'


@simple_page.route('/my/route/')
def new_my():
    # new endpoint / should works instead my()
    return 'new'

# map of views which we won't register in Flask app
# you can store this somewhere in settings
SKIP_VIEWS = (
    # route, view function
    ('/my/route/', my, ),
)


class CustomFlask(Flask):

    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        # Flask registers views when an application starts
        # do not add view from SKIP_VIEWS
        for rule_, view_func_ in SKIP_VIEWS:  # type: str, func
            if rule_ == rule and view_func == view_func_:
                return
        return super(CustomFlask, self).add_url_rule(rule, endpoint, view_func, **options)


app = CustomFlask(__name__)
app.register_blueprint(simple_page)
app.run(debug=True)

Second way:

two.py - default blueprint with endpoint

from flask import Blueprint

bp_two = Blueprint('simple_page2', __name__, )


@bp_two.route('/my/route/')
def default():
    return 'default'

test.py - your blueprint + app

from flask import Flask, Blueprint

from two import bp_two

your_bp = Blueprint('simple_page', __name__, )


@your_bp.route('/my/route/')
def new_route():
    return 'new'


app = Flask(__name__)
# register blueprint and turn off '/my/route/' endpoint
app.register_blueprint(bp_two, **{'url_defaults': {'/my/route/': None}})
app.register_blueprint(your_bp)

app.run(debug=True)

Run app. Open /my/route/. You will see that default endpoint wasn't add/works.

Hope this helps.

like image 184
Danila Ganchar Avatar answered Oct 11 '22 14:10

Danila Ganchar