在Flask中寻找url_for的反转

时间:2013-10-02 03:10:48

标签: python json rest flask werkzeug

我正在使用FlaskFlask-RESTful来构建REST API。在此API中,我的一些资源包含与其他资源的URL关系。

当对这些资源执行POST请求时,我发现我需要使用Flask的url_for()函数的反转来解析传入的URL。

例如,对https://www.example.com/buildings的POST可能包含以下json:

{
  "address": "123 Lyall St",
  ...
  "owner": {
      "href": "https://www.example.com/users/21414512"
  },
  "tenant": {
      "href": "https://www.example.com/users/16324642"
  },
}

我想使用以下路线解析ownertenant中的ID:

"https://www.example.com/users/<int:id>"

在Flask或Werkzueg中有没有方便的方法可以做到这一点,还是我应该自己解析网址?能够重新使用已经定义的路线真是太好了......

我发现了this帖子,但它似乎没有描述如何在请求之外执行此操作。

2 个答案:

答案 0 :(得分:9)

创建测试请求上下文的最简单方法(感谢 Leon Young ):

with app.test_request_context(YOUR_URL) as request_ctx:
    url_rule = request_ctx.request.url_rule

但是创建请求上下文的所有意义都是:

from flask.testing import make_test_environ_builder

builder = make_test_environ_builder(app, YOUR_URL)
environ = builder.get_environ()
url_adapter = app.url_map.bind_to_environ(environ)
url_rule, view_args = url_adapter.match(return_rule=True)

如果没有理由检查协议和主机,您可以创建特殊匹配方法:

from functools import partial

url_adapter = app.url_map.bind('localhost')
match = partial(url_adapter.match, return_rule=True)

在没有协议和主持人的情况下使用它:

owner_url_rule, owner_view_args = match('/users/21414512')
tenant_url_rule, tenant_view_args = match('/users/16324642')

答案 1 :(得分:3)

我使用下面的route_from函数:

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)

我是通过查看url_for的实现并将其撤消来写的。

url参数可以是完整的URL,也可以只是路径信息部分。返回值是一个带有端点名称的元组和一个带有参数的dict

免责声明:我没有广泛测试过。我计划最终将其作为拉取请求提交,但似乎永远不会完全测试它并编写一些单元测试。如果它不适合你,请告诉我!