如何在Bottle中从路径获取参数?
当我执行这个网址时:
http://domain:8081/forum?id=2&page=26
用这段代码:
@route('/forum')
def display_forum():
forum_id = request.query.id
page = request.query.page or '1'
return template('Forum ID: {{id}} (page {{page}})', id=forum_id, page=page)
网页上返回了 论坛 ID: 2 (第 26 页)
我想通过调用一个动态的 REST URL 来获得相同的结果。这个网址可以是 http://domain:8081/forum/2/26
或者 http://domain:8081/forum/city/place/day/hour
。
参数的数量并不是固定的。我在 Bottle 的文档中看到了一些想法,可能可以用类似通配符过滤器 :path
的东西。
4 个回答
0
我的解决办法是把表单里的值和查询里的值结合起来,形成一个统一的接口。
def merge_dicts(*args):
result = {}
for dictionary in args:
result.update(dictionary)
return result
payload = merge_dicts(dict(request.forms), dict(request.query.decode()))
id = payload['id']
page = payload['page']
0
我会使用:path
这个通配符过滤器,就像你提到的那样。在你的例子中,你提供了带有键值对的查询参数,并询问如何用网址路径来实现同样的功能,但只使用值,并且没有固定参数数量的限制。
比如说:
/forum?id=2&page=26
/forum/2/6
因为我们不想限制参数的数量,我觉得在网址路径中以成对的方式提供键是有道理的。
比如:
/forum/id/2/page/26/city/chicago/place/opera/day/monday/hour/2:20pm
然后我会根据这个进行解析:
from bottle import route, run, request, template
import re
@route("/forum/<url_paths:path>", method=["GET", "POST"])
def display_forum(url_paths=None):
# -- parse the paths as pairs of /key/value/key/value...
match = re.compile(r"/", re.VERBOSE)
items = map(str, match.split(url_paths))
url_params = dict(zip(items, items))
# -- check for any GET or POST parameters and save as dict(),
req_params = {k:v for (k,v) in request.params.items()}
# -- merge the url_params with req_params into one dictionary object
params = url_params | req_params
# -- parse forum_id and page
if params:
forum_id = params.pop("id") if params.get("id") else "NA"
page = params.pop("page") if params.get("page") else "1"
tpl = """
Forum ID: {{id}} (page {{page}})
% for (key, value) in params.items():
{{key}}: {{value}}
%end
"""
return template(tpl, id=forum_id, page=page, params=params)
return "please provide url paths, query params, or post data"
run(host="0.0.0.0", port=8081, reloader=True)
示例请求
仅网址路径
❯ curl "http://127.0.0.1:8081/forum/city/Miami/place/Dog%20Park/day/Wednesday/hour/8:20pm/id/8/page/7"
Forum ID: 8 (page 7)
city: Miami
place: Dog Park
day: Wednesday
hour: 8:20pm
网址路径和查询参数
❯ curl "http://127.0.0.1:8081/forum/city/Chicago/place/Opera%20House/day/Saturday/hour/6:20pm?id=2&page=26"
Forum ID: 2 (page 26)
city: Chicago
place: Opera House
day: Saturday
hour: 6:20pm
网址路径和POST参数
❯ curl -X POST "http://127.0.0.1:8081/forum/event/Yoga/city/Philadelphia/place/Gym/day/Tuesday/hour/8:00am" -d "id=2&page=3"
Forum ID: 2 (page 3)
event: Yoga
city: Philadelphia
place: Gym
day: Tuesday
hour: 8:00am
网址路径和POST表单字段
❯ curl -X POST "http://127.0.0.1:8081/forum/event/Concert/city/Virginia%20Beach/place/GTE%20Amphitheatre/day/Friday/hour/7:20pm/price/\$65.00" -F "id=3" -F "page=16"
Forum ID: 3 (page 16)
event: Concert
city: Virginia Beach
place: GTE Amphitheatre
day: Friday
hour: 7:20pm
price: $65.00
0
使用参数
@route ('/forum/forum_id=:forum_id&page=:page')
def display_forum(forum_id,page):
forum_id = request.query.id
page = request.query.page or '1'
return template('Forum ID: {{id}} (page {{page}})', id=forum_id, page=page)
3
这个方法不能无限制地扩展到很多条路线,但像这样的做法是可行的。
@route('/forum/<first>')
def test(first):
return first
@route('/forum/<first>/<second>')
def test(first, second):
return first, second
@route('/forum/<first>/<second>/<third>')
def test(first, second, third):
return first, second, third
@route('/forum/<first>/<second>/<third>/<fourth>')
def test(first, second, third, fourth):
return first, second, third, fourth