'How to get parameters from path in Bottle?
When i execute this url:
http://domain:8081/forum?id=2&page=26
with this code:
@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)
This return on webpage Forum ID: 2 (page 26)
I need to obtain the same result calling a dynamic rest url.
The url can be http://domain:8081/forum/2/26
or http://domain:8081/forum/city/place/day/hour
.
Don't exist a fixed number of parameters.
I saw some ideas in bottle documentation, perhaps something like wildcard filter :path
.
Solution 1:[1]
It won't scale to infinite routes, but something like this would work.
@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
Solution 2:[2]
Use Parameters
@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)
Solution 3:[3]
I would use the :path
wildcard filter as you have hinted.
In your example, you provided query parameters with key=value pairs and asked how to do the same using url paths but only using values with no limit of a fixed number of parameters.
/forum?id=2&page=26
/forum/2/6
Since we don't want a limit to the number of parameters, I feel that it makes sense to provide the keys in the url paths as pairs.
/forum/id/2/page/26/city/chicago/place/opera/day/monday/hour/2:20pm
Then I would parse it accordingly:
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)
Sample Requests
only url paths
? 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
url paths and query params
? 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
url paths and POST params
? 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
url paths and POST form fields
? 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
Solution 4:[4]
My solution is to combine the form values with the query values making a unified API.
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']
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | user1071182 |
Solution 2 | Senthilnathan |
Solution 3 | Teddy Katayama |
Solution 4 | eatmeimadanish |