获取与某个url匹配的Flask视图函数

问题描述 投票:0回答:3

我有一些 url 路径,想要检查它们是否指向我的 Flask 应用程序中的 url 规则。我如何使用 Flask 检查这一点?

from flask import Flask, json, request, Response

app = Flask('simple_app')

@app.route('/foo/<bar_id>', methods=['GET'])
def foo_bar_id(bar_id):
    if request.method == 'GET':
        return Response(json.dumps({'foo': bar_id}), status=200)

@app.route('/bar', methods=['GET'])
def bar():
    if request.method == 'GET':
        return Response(json.dumps(['bar']), status=200)
test_route_a = '/foo/1'  # return foo_bar_id function
test_route_b = '/bar'  # return bar function
python flask werkzeug
3个回答
28
投票

app.url_map
存储将规则与端点进行映射和匹配的对象。
app.view_functions
将端点映射到视图函数。

调用

match
将 URL 与端点和值进行匹配。如果找不到路由,则会引发 404;如果指定了错误的方法,则会引发 405。您需要匹配方法和网址。

重定向被视为异常,您需要递归地捕获和测试这些以找到视图函数。

可以添加不映射到视图的规则,您在查找视图时需要抓住

KeyError

from werkzeug.routing import RequestRedirect, MethodNotAllowed, NotFound

def get_view_function(url, method='GET'):
    """Match a url and return the view and arguments
    it will be called with, or None if there is no view.
    """

    adapter = app.url_map.bind('localhost')

    try:
        match = adapter.match(url, method=method)
    except RequestRedirect as e:
        # recursively match redirects
        return get_view_function(e.new_url, method)
    except (MethodNotAllowed, NotFound):
        # no match
        return None

    try:
        # return the view function and arguments
        return app.view_functions[match[0]], match[1]
    except KeyError:
        # no view is associated with the endpoint
        return None

还有更多选项可以传递给

bind
来影响匹配的方式,请参阅文档了解详细信息。

视图函数也可能引发 404(或其他)错误,因此这只能保证 url 与视图匹配,而不能保证视图返回 200 响应。


0
投票

除了@davidism的回答(flask的核心开发者)。 注意,如果你想发现flask app处理的当前url的视图函数。您可以使用 Flask 的

Request
对象:

Flask 中默认使用的请求对象。记得 匹配的端点和视图参数。

Flask.view_functtions
其中:

#:将端点名称映射到视图函数的字典。 #: 要注册视图函数,请使用 :meth:

route
装饰器。

 def get_view_function():
     if request.url_rule:
        return current_app.view_functions.get(request.url_rule.endpoint, None)

0
投票

为了补充此处给出的其他答案,对于任何想要对 Flask 基于类的视图执行此操作的人,您将看到

app.view_functions
返回基本 View 类的视图方法,而不是其中的具体类你定义了你的观点:

In [4]: rule_generator = app.url_map.iter_rules()

In [5]: rule = next(rule_generator)

In [6]: rule

Out[6]: <Rule '/api/helloworld' (GET, OPTIONS, HEAD) -> helloworld_view>

In [7]: app.view_functions.get(rule.endpoint, None)

Out[7]: <function test_app.views.View.as_view.<locals>.view(**kwargs: Any) -> Union[ForwardRef('Response'), str, bytes, List[Any], Mapping[str, Any], Iterator[str], Iterator[bytes], Tuple[Union[ForwardRef('Response'), str, bytes, List[Any], Mapping[str, Any], Iterator[str], Iterator[bytes]], Union[ForwardRef('Headers'), Mapping[str, Union[str, List[str], Tuple[str, ...]]], Sequence[Tuple[str, Union[str, List[str], Tuple[str, ...]]]]]], Tuple[Union[ForwardRef('Response'), str, bytes, List[Any], Mapping[str, Any], Iterator[str], Iterator[bytes]], int], Tuple[Union[ForwardRef('Response'), str, bytes, List[Any], Mapping[str, Any], Iterator[str], Iterator[bytes]], int, Union[ForwardRef('Headers'), Mapping[str, Union[str, List[str], Tuple[str, ...]]], Sequence[Tuple[str, Union[str, List[str], Tuple[str, ...]]]]]], ForwardRef('WSGIApplication')]>

解决方案只是多了一步,就是调用

view_class
成员:

In [8]: rule_endpoint = app.view_functions.get(rule.endpoint, None)

In [9]: rule_endpoint.view_class

Out[9]: test_app.views.HelloView

要处理视图函数和类的混合,您可以执行以下操作:

if hasattr(view, "view_class"):
    view_definition = view.view_class
else:
    view_definition = view
# Do something with this information, e.g.
view_name = view_definition.__name__
© www.soinside.com 2019 - 2024. All rights reserved.