qff
qff

Reputation: 5932

Having the view function – how do I get the URL of a Blueprint route in Flask?

The cache system I'm using (Flask-Cache) uses URLs to calculate cache keys. From a different place in the code I get passed a view function, and then need to check if the view has been cached.

Firstly, the current iteration of Flask-Cache needs the request to calculate the cache key, but I have made a patch that fixes the deficiency for simple cases, by getting the URL with url_for(view_function.__name__, **kwargs).

The problem is that now I've started using Flask Blueprints, and simply using view_function.__name__ in url_for will not find the blueprint route (raises BuildError).

Simple Flask app

@app.route('/user/<user_id>')
def user_page(user_id):
    return 'Hello user %s' % user_id

def check_cache(view_function, **kwargs):
    url = url_for(view_function.__name__, **kwargs)
    ... use URL to check cache ...

check_cache(user_page, user_id='123')

Blueprint Flask app

from flask import Blueprint    

bp = Blueprint('user_blueprint', __name__)

@bp.route('/user/<user_id>')
def user_page(user_id):
    return 'Hello user %s' % user_id

def check_cache(view_function, **kwargs):
    url = url_for(view_function.__name__, **kwargs) # WON'T WORK WITH BLUEPRINTS
    ... use URL to check cache ...

check_cache(user_page, user_id='123')

How do I get the URL for the route/view function, when it's defined via a Blueprint?

Or alternatively, how do I make cache keys that will work when using blueprints? (And can be calculated via a decorator on a view function, and doesn't clash when two or more blueprints have view functions with the same name)

Upvotes: 1

Views: 4382

Answers (2)

Peter Trotman
Peter Trotman

Reputation: 433

Blueprints, by default, prepend the endpoint name with the blueprint name. In this way, the url_for string:

url = url_for('user_page')

Becomes:

url = url_for('user_blueprint.user_page')

Now, you are creating your url_for strings with the function name, so you can either switch to explicitly passing the endpoint strings as above, or use:

url = url_for('user_blueprint.' + view_function.__name__)

I don't know of a programmatic way to automatically find the blueprint name from the view_function.

Upvotes: 3

r-m-n
r-m-n

Reputation: 15100

Try with app.view_functions

def check_cache(view_function, **kwargs):
    flipped_view_functions_dict = dict((v, k) for k, v in app.view_functions.iteritems())
    view_name = flipped_view_functions_dict[view_function]
    url = url_for(view_name, **kwargs)
    ... use URL to check cache ...

Upvotes: 2

Related Questions