Python 将Flask中的URL还原为端点+;论据
解析Flask中的URL以检索对端点的引用以及所有参数的字典的合适方法是什么 为了提供一个示例,给定此路径,我想将Python 将Flask中的URL还原为端点+;论据,python,flask,Python,Flask,解析Flask中的URL以检索对端点的引用以及所有参数的字典的合适方法是什么 为了提供一个示例,给定此路径,我想将'/user/nick'解析为profile,{'username':'nick'}: @app.route(“/user/”) def配置文件(用户名):通过 根据我目前的研究,Flask中的所有路由都存储在app.url\u map下。map是的一个实例,它有一个方法match(),原则上可以实现我所寻找的功能。但是,该方法是类的内部方法。这就是我为此目的而进行的黑客攻击,查看
'/user/nick'
解析为profile
,{'username':'nick'}
:
@app.route(“/user/”)
def配置文件(用户名):通过
根据我目前的研究,Flask中的所有路由都存储在
app.url\u map
下。map是的一个实例,它有一个方法match()
,原则上可以实现我所寻找的功能。但是,该方法是类的内部方法。这就是我为此目的而进行的黑客攻击,查看url\u 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)
此方法的返回值是一个元组,第一个元素是端点名称,第二个元素是带有参数的字典
我没有对它进行过广泛的测试,但它在所有情况下都对我有效。我知道我的答案来得很晚,但我遇到了同样的问题,找到了一种更简单的方法:
请求。查看参数
。例如:
我认为:
@app.route('/user/<username>')
def profile(username):
return render_template("profile.html")
@app.route(“/user/”)
def配置文件(用户名):
返回渲染模板(“profile.html”)
在profile.html
中:
{{request.view_args}}
访问url时http://localhost:4999/user/sam
,我得到:{'username':u'sam}
您还可以通过
request.endpoint
获取获得视图的函数的名称。我重写了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.
请问你为什么要这样做?这类事情通常由Flask本身处理(如您所建议的,它使用映射的
match()
方法)。为什么你需要做Flask已经做过的事情?@MarkHildreth:这种方法的一个用途是在RESTful API中,当你得到一个资源URL作为参数,你需要将它解码回端点和参数。这正是我的场景。我正在构建一个REST服务。@Miguel在这里使用相同的用例。谢谢你的提问和回答。你好,山姆,我的问题是关于获取任意URL的端点,不一定是当前正在访问的URL。谢谢你的回答。我也想正确处理子域,结果我不得不为此构造一个新的请求和URL适配器,所以我给出了这个实现的一个新答案。