I am using Flask and Flask-RESTful to build a REST API. Within this API some of my resources contain url relations to other resources.
When performing POST requests to these resources I am finding that I am needing the inverse of Flask's url_for() function to parse the incoming url.
For example, a POST to https://www.example.com/buildings
may contain the following json:
{
"address": "123 Lyall St",
...
"owner": {
"href": "https://www.example.com/users/21414512"
},
"tenant": {
"href": "https://www.example.com/users/16324642"
},
}
I would like to parse the id out of owner
and tenant
using the following route:
"https://www.example.com/users/<int:id>"
Is there a convenient way to do this within Flask or Werkzueg or should I just parse the url myself? It would be nice to be able to re-use the already defined route...
I found this post but it does not seem to describe how to do it outside of a request.
I use the route_from
function below:
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)
I wrote this by looking at the implementation of url_for
and reversing it.
The url
argument can be a complete URL or just the path info portion. The return value is a tuple with the endpoint name and a dict
with the arguments.
Disclaimer: I haven't tested it extensively. I was planning to eventually submit it as a pull request, but never seem to get around to fully test it and write some unit tests. If it does not work for you, let me know!