9

在 Flask 中解析 URL 以检索对端点的引用以及所有参数的字典的适当方法是什么?

举个例子,给定这条路线,我想解析'/user/nick'profile, {'username': 'nick'}

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

从我目前的研究来看,Flask 中的所有路由都存储在app.url_map. 该地图是werkzeug.routing.Map的一个实例,它有一个match()原则上可以做我正在寻找的方法。但是,该方法是类的内部方法。

4

3 回答 3

10

这就是我为此目的而破解的,查看url_for()并反转它:

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)

此方法的返回值是一个元组,第一个元素是端点名称,第二个元素是带有参数的字典。

我没有对它进行广泛的测试,但它在所有情况下都对我有用。

于 2013-10-28T14:17:29.230 回答
2

我知道我迟到了答案,但我遇到了同样的问题并找到了一种更简单的方法来获得它:request.view_args. 例如:

在我看来:

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

profile.html:{{request.view_args}}

访问 urlhttp://localhost:4999/user/sam时,我得到:{'username': u'sam'}

您还可以使用 获取获得视图的函数的名称request.endpoint

于 2015-08-20T05:25:35.283 回答
0

我重写了 Miguel 的实现以支持子域:

from flask import current_app, request
from six.moves.urllib.parse import urlsplit

def endpoint_for(url, method=None, return_rule=False, follow_redirects=True):
    """
    Given an absolute URL, retrieve the matching endpoint name (or rule).
    Requires a current request context to determine runtime environment.

    :param str method: HTTP method to use (defaults to GET)
    :param bool return_rule: Return the URL rule instead of the endpoint name
    :param bool follow_redirects: Follow redirects to final endpoint
    :return: Endpoint name or URL rule, or `None` if not found
    """
    parsed_url = urlsplit(url)
    if not parsed_url.netloc:
        # We require an absolute URL
        return

    # Take the current runtime environment...
    environ = dict(request.environ)
    # ...but replace the HTTP host with the URL's host...
    environ['HTTP_HOST'] = parsed_url.netloc
    # ...and the path with the URL's path (after discounting the app path, if not hosted at root).
    environ['PATH_INFO'] = parsed_url.path[len(environ['SCRIPT_NAME']):]
    # Create a new request with this environment...
    url_request = current_app.request_class(environ)
    # ...and a URL adapter with the new request.
    url_adapter = current_app.create_url_adapter(url_request)

    # Domain or subdomain must match.
    # TODO: To support apps that host multiple domains, we need to remove this
    # check, or offer a callback hook to check the domain.
    if parsed_url.netloc != url_adapter.server_name and not (
            parsed_url.netloc.endswith('.' + url_adapter.server_name)):
        return

    try:
        endpoint_or_rule, view_args = url_adapter.match(parsed_url.path, method, return_rule=return_rule)
        return endpoint_or_rule
    except RequestRedirect as r:
        # A redirect typically implies `/folder` -> `/folder/`
        # This will not be a redirect response from a view, since the view isn't being called
        if follow_redirects:
            return endpoint_for(r.new_url, method=method, return_rule=return_rule, follow_redirects=follow_redirects)
    except HTTPException as e:
        pass
    # If we got here, no endpoint was found.
于 2018-08-16T06:04:55.683 回答