我不确定你能做你想做的事。但是,根据您上面描述的用法,我认为您只需要一个转换器。
什么是转换器?
正是这种魔力让您可以像这样定义路由:
@app.route('/double/<int:number>')
def double(number):
return '%d' % (number * 2)
上面,路由只接受 /double/ ints
。更好的是,在 url 部分中传递的任何内容都将转换为 int。因此,转换器绰号:D。
转换器遵循<converter:variable_name>
格式。您可以在此处阅读有关 Flask 的内置转换器的信息。
转换器最好的部分是您可以为自定义数据类型编写自己的!为此,只需从werkzeug.routing.BaseConverter派生并填写 to_python 和 to_url。下面,我为无处不在的 User 对象创建了一个简单的转换器。
class UserConverter(BaseConverter):
"""Converts Users for flask URLs."""
def to_python(self, value):
"""Called to convert a `value` to its python equivalent.
Here, we convert `value` to a User.
"""
# Anytime an invalid value is provided, raise ValidationError. Flask
# will catch this, and continue searching the other routes. First,
# check that value is an integer, if not there is no way it could be
# a user.
if not value.isdigit():
raise ValidationError()
user_id = int(value)
# Look up the user in the database.
if user_id not in _database:
raise ValidationError()
# Otherwise, return the user.
return _database[user_id]
def to_url(self, value):
"""Called to convert a `value` to its `url` equivalent.
Here we convert `value`, the User object to an integer - the user id.
"""
return str(value.id)
转换器什么时候被调用?
当烧瓶与您的路线匹配并需要填写转换器处理的位置时。因此,给定以下路由 - /find/<user:user>
,下面的所有 URL 都由我们的转换器处理。
- /查找/1
- /查找/2
- /找到/杰米
- /查找/zasdf123
对于上面的 url,UserConverter.to_python 方法是用 '1'、'2'、'jaime' 和 'zasdf123' 调用的。由方法决定这些值是否转换为有效用户。如果是这样,则将有效用户直接传递给路由的user
参数。
但是,flask 仍然需要了解您的新转换器。这很简单:
app.url_map.converters['user'] = UserConverter
自定义转换器的最后一个很酷的功能是它们使构建 URL 成为一个自然、简单的过程。要创建一个 url,只需执行以下操作:
url_for('find_user', user=user)
最后,一个简单的程序将所有这些联系在一起。
from flask import Flask, url_for
from werkzeug.routing import BaseConverter, ValidationError
class User:
def __init__(self, id, name):
self.id = id
self.name = name
class UserConverter(BaseConverter):
"""Converts Users for flask URLs."""
def to_python(self, value):
"""Called to convert a `value` to its python equivalent.
Here, we convert `value` to a User.
"""
# Anytime an invalid value is provided, raise ValidationError. Flask
# will catch this, and continue searching the other routes. First,
# check that value is an integer, if not there is no way it could be
# a user.
if not value.isdigit():
raise ValidationError()
user_id = int(value)
# Look up the user in the database.
if user_id not in _database:
raise ValidationError()
# Otherwise, return the user.
return _database[user_id]
def to_url(self, value):
"""Called to convert a `value` to its `url` equivalent.
Here we convert `value`, the User object to an integer - the user id.
"""
return str(value.id)
# Create a `database` of users.
_database = {
1: User(1, 'Bob'),
2: User(2, 'Jim'),
3: User(3, 'Ben')
}
app = Flask(__name__)
app.url_map.converters['user'] = UserConverter
@app.route('/find/<user:user>')
def find_user(user):
return "User: %s" % user.name
@app.route('/find/<user:user>/extrapath')
def find_userextra(user):
return 'User extra: %s' % user.name
@app.route('/users')
def list_users():
# Return some broken HTML showing url's to our users.
s = ''
for user in _database.values():
s += url_for('find_user', user=user) + '<br/>'
return s
if __name__ == '__main__':
app.run(debug=True)
如果有不清楚的地方,或者存在错误,请告诉我:D。这适用于您的问题,因为您提到了一系列以相同开头的网址-
/user/1/something
/user/1/something-else
/user/2/
对于这些路线,您可以像这样应用自定义转换器:
@app.route('/user/<user:user>/something')
@app.route('/user/<user:user>/something-else')
@app.route('/user/<user:user>/)