Reputation: 5854
I am sure there is an answer to this but I cannot seem to find it. Also, important to note that I am very new to Python.
I recently cloned this repo which uses python and wsgi https://github.com/hypothesis/via for routing.
What I want is to have a param in the url path (no query string) as such:
meow.com/cat_articles/:article_id # i.e. meow.com/cat_articles/677
How can I achieve that?
For reference, my end goal is to add my own path to this file:
https://github.com/hypothesis/via/blob/master/via/app.py
Upvotes: 7
Views: 1351
Reputation: 3780
Firstly I'm not quite sure if you want to modify the via project or just create something similar from scratch.
Upon inspection of the source code the via project shows to be based on the Werkzueg-library, which provides a URL Routing API supporting what your looking for
from werkzeug.wrappers import Request, Response
from werkzeug.wsgi import responder
from werkzeug.routing import Map, Rule
def show_cat_article(article_id):
...
url_map = Map(
[Rule("cat_articles/<int:article_id>", endpoint="show_cat_article")]
)
views = {"show_cat_article": show_cat_article}
@responder
def application(environ, start_response):
request = Request(environ)
urls = url_map.bind_to_environ(environ)
return urls.dispatch(lambda e, v: views[e](request, **v),
catch_http_exceptions=True)
Now if you're not constrained to using plain werkzeug directly I'd recommend taking a look into Flask by the same team, if your not familiar with flask it's described as follows "Flask is a microframework for Python based on Werkzeug, …". So basically a lightweight wrapper with convenient features.
Flask allows you to add a route with params via a decorator like this:
@app.route("meow.com/cat_articles/<int:article_id>")
def show_cat_article(article_id):
...
Or using less magically using add_url_rule(…) (which is invoked by the decorator).
def show_cat_article(article_id):
...
app.add_url_rule("meow.com/cat_articles/<int:article_id>", show_cat_article)
Upvotes: 2
Reputation: 173
Have you considered this library? I think it will do the job for you!
https://pypi.org/project/uritemplate/
Upvotes: 0
Reputation: 601
How you'd add such a route to an app depends on what library or libraries that app is using to implement WSGI. I see that the app.py
file you linked to is using werkzeug
(as well as static
).
Here are some useful references for routing with placeholders in werkzeug
:
I've barely used werkzeug
and won't claim this is definitely the best approach, but one option would be to add another WSGI app via werkzeug
to the wsgi.DispatcherMiddleware
call at the bottom of that file.
Here's some thrown-together sample code to get you started in the context of the app.py
file you shared. Try deleting everything after this line and replacing it with this code:
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import HTTPException
my_url_map = Map([
# Note that this rule builds on the `/cat_articles` prefix used in the `DispatcherMiddleware` call further down
Rule('/<article_id>', endpoint='get_cat_article')
])
def cat_app(environ, start_response):
urls = my_url_map.bind_to_environ(environ)
try:
endpoint, args = urls.match()
except HTTPException, e:
return e(environ, start_response)
if endpoint == 'get_cat_article':
# Note that werkzeug also provides objects for building responses: http://werkzeug.pocoo.org/docs/0.14/wrappers
start_response('200 OK', [('Content-Type', 'text/plain')])
return ['Finally, a cat-centric article about {0}'.format(args['article_id'])]
else:
start_response('404 Not Found', [('Content-Type', 'text/plain')])
return ['Nothing is here...']
application = RequestHeaderSanitiser(app)
application = ResponseHeaderSanitiser(application)
application = Blocker(application)
application = UserAgentDecorator(application, 'Hypothesis-Via')
application = wsgi.DispatcherMiddleware(application, {
'/cat_articles': cat_app,
'/favicon.ico': static.Cling('static/favicon.ico'),
'/robots.txt': static.Cling('static/robots.txt'),
'/static': static.Cling('static/'),
'/static/__pywb': static.Cling(resource_filename('pywb', 'static/')),
'/static/__shared/viewer/web/viewer.html': redirect_old_viewer,
'/h': redirect_strip_matched_path,
})
With that code, the path /cat_articles/plants
should return:
Finally, a cat-centric article about plants
Upvotes: 4