python 获取匹配url的Flask视图函数

vmjh9lq9  于 2023-09-29  发布在  Python
关注(0)|答案(3)|浏览(127)

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

  1. from flask import Flask, json, request, Response
  2. app = Flask('simple_app')
  3. @app.route('/foo/<bar_id>', methods=['GET'])
  4. def foo_bar_id(bar_id):
  5. if request.method == 'GET':
  6. return Response(json.dumps({'foo': bar_id}), status=200)
  7. @app.route('/bar', methods=['GET'])
  8. def bar():
  9. if request.method == 'GET':
  10. return Response(json.dumps(['bar']), status=200)
  1. test_route_a = '/foo/1' # return foo_bar_id function
  2. test_route_b = '/bar' # return bar function
r3i60tvu

r3i60tvu1#

app.url_map存储将规则与端点Map和匹配的对象。app.view_functions将端点Map到视图函数。
调用match将url与端点和值进行匹配。如果没有找到路由,则会引发404,如果指定了错误的方法,则会引发405。你需要方法和url来匹配。
重定向被视为异常,您需要递归地捕获和测试这些异常以找到视图函数。
可以添加不Map到视图的规则,在查找视图时需要捕获KeyError

  1. from werkzeug.routing import RequestRedirect, MethodNotAllowed, NotFound
  2. def get_view_function(url, method='GET'):
  3. """Match a url and return the view and arguments
  4. it will be called with, or None if there is no view.
  5. """
  6. adapter = app.url_map.bind('localhost')
  7. try:
  8. match = adapter.match(url, method=method)
  9. except RequestRedirect as e:
  10. # recursively match redirects
  11. return get_view_function(e.new_url, method)
  12. except (MethodNotAllowed, NotFound):
  13. # no match
  14. return None
  15. try:
  16. # return the view function and arguments
  17. return app.view_functions[match[0]], match[1]
  18. except KeyError:
  19. # no view is associated with the endpoint
  20. return None

还有更多的选项可以传递给bind来影响如何进行匹配,有关详细信息,请参阅文档。
view函数也可能引发404(或其他)错误,因此这只能保证url与视图匹配,而不能保证视图返回200响应。

展开查看全部
cuxqih21

cuxqih212#

除了@davidism的答案(flask的核心开发者)。注意,如果你想发现flask app处理的当前url的view函数。你可以使用flask的Request对象:
Flask中默认使用的请求对象。记住匹配的端点和视图参数。
以及Flask.view_functtions,其中:

:将端点名称Map到视图函数的字典。#:要注册视图函数,请使用:meth:route装饰器。

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

ngynwnxp3#

为了补充这里给出的其他答案,对于任何想要为Flask的基于类的视图做这件事的人来说,你会看到app.view_functions返回基类View的view方法,而不是你定义视图的具体类:

  1. In [4]: rule_generator = app.url_map.iter_rules()
  2. In [5]: rule = next(rule_generator)
  3. In [6]: rule
  4. Out[6]: <Rule '/api/helloworld' (GET, OPTIONS, HEAD) -> helloworld_view>
  5. In [7]: app.view_functions.get(rule.endpoint, None)
  6. 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成员:

  1. In [8]: rule_endpoint = app.view_functions.get(rule.endpoint, None)
  2. In [9]: rule_endpoint.view_class
  3. Out[9]: test_app.views.HelloView

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

  1. if hasattr(view, "view_class"):
  2. view_definition = view.view_class
  3. else:
  4. view_definition = view
  5. # Do something with this information, e.g.
  6. view_name = view_definition.__name__
展开查看全部

相关问题