Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverting a URL in Flask to the endpoint + arguments

Tags:

python

flask

What would be the appropriate way of resolving a URL within Flask to retrieve a reference to the endpoint as well as a dictionary of all the arguments?

To provide an example, given this route, I'd like to resolve '/user/nick' to profile,{'username': 'nick'}:

@app.route('/user/<username>')
def profile(username): pass

From my research so far, all routes in Flask are stored under app.url_map. The map is an instance of werkzeug.routing.Map and it has a method match() that would in principle do what I am looking for. However, that method is internal to the class.

like image 656
lyschoening Avatar asked Oct 28 '13 09:10

lyschoening


People also ask

How do you change the URL on a Flask?

The url_for() function is used to build a URL to the specific function dynamically. The first argument is the name of the specified function, and then we can pass any number of keyword argument corresponding to the variable part of the URL.

How do you pass arguments on the Flask app?

How do you pass arguments in Flask API? Required Arguments To require a value be passed for an argument, just add required=True to the call to add_argument() . parser. add_argument('name', required=True, help="Name cannot be blank!")

What is URL routing in Flask?

Routing in FlaskThe route() decorator in Flask is used to bind an URL to a function. As a result when the URL is mentioned in the browser, the function is executed to give the result. Here, URL '/hello' rule is bound to the hello_world() function.


2 Answers

This is what I hacked for this purpose looking at url_for() and reversing it:

from flask.globals import _app_ctx_stack, _request_ctx_stack
from werkzeug.urls import url_parse

def route_from(url, method = None):
    appctx = _app_ctx_stack.top
    reqctx = _request_ctx_stack.top
    if appctx is None:
        raise RuntimeError('Attempted to match a URL without the '
                           'application context being pushed. This has to be '
                           'executed when application context is available.')

    if reqctx is not None:
        url_adapter = reqctx.url_adapter
    else:
        url_adapter = appctx.url_adapter
        if url_adapter is None:
            raise RuntimeError('Application was not able to create a URL '
                               'adapter for request independent URL matching. '
                               'You might be able to fix this by setting '
                               'the SERVER_NAME config variable.')
    parsed_url = url_parse(url)
    if parsed_url.netloc is not "" and parsed_url.netloc != url_adapter.server_name:
        raise NotFound()
    return url_adapter.match(parsed_url.path, method)

The return value of this method is a tuple, with the first element being the endpoint name and the second a dictionary with the arguments.

I haven't tested it extensively, but it worked for me in all cases.

like image 130
Miguel Avatar answered Oct 08 '22 20:10

Miguel


I know I am coming in late with an answer, but I ran into the same problem and found a simpler way to get it: request.view_args. For example:

In my views:

@app.route('/user/<username>')
def profile(username): 
    return render_template("profile.html")

In profile.html: {{request.view_args}}

When visiting the url http://localhost:4999/user/sam, I get: {'username': u'sam'}.

You can also get the name of the function that got your view with request.endpoint.

like image 24
S4M Avatar answered Oct 08 '22 21:10

S4M