如何使用 wsgi 在 URL 路径中包含变量? (不是查询字符串)

How to include a variable in URL path using wsgi? (not query string)

我确定对此有答案,但我似乎找不到。另外,重要的是要注意我对 Python.

很陌生

我最近克隆了这个使用 python 和 wsgi https://github.com/hypothesis/via 进行路由的 repo。

我想要的是在 url 路径中有一个参数(没有查询字符串):

meow.com/cat_articles/:article_id # i.e. meow.com/cat_articles/677

我怎样才能做到这一点?

供参考,我的最终目标是将我自己的路径添加到此文件:

https://github.com/hypothesis/via/blob/master/via/app.py

如何将这样的路由添加到应用程序取决于该应用程序使用哪个或哪些库来实现 WSGI。我看到您链接到的 app.py 文件正在使用 werkzeug(以及 static)。

这里有一些有用的参考,用于在 werkzeug 中使用占位符进行路由:

我几乎没有使用过 werkzeug 并且不会声称这绝对是最好的方法,但是一个选择是通过 werkzeug 添加另一个 WSGI 应用程序到 wsgi.DispatcherMiddleware在该文件的底部调用。

这里有一些综合示例代码,可帮助您在共享的 app.py 文件的上下文中入门。尝试删除 this line 之后的所有内容并用此代码替换它:

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,
})

使用该代码,路径 /cat_articles/plants 应该 return:

Finally, a cat-centric article about plants

你考虑过这个图书馆吗?我认为它会为您完成工作!

https://pypi.org/project/uritemplate/

纯 werkzueg 路径

首先,我不太确定你是想修改 via 项目还是只是从头开始创建类似的东西。

检查源代码后,via 项目显示基于 Werkzueg-library, which provides a URL Routing API 支持您寻找的内容

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)

更简单的路线

现在,如果您不局限于直接使用普通的 werkzeug,我建议您查看同一个团队的 Flask,如果您不熟悉 Flask,其描述如下 "Flask is a microframework for Python based on Werkzeug, …"。所以基本上是一个具有方便功能的轻量级包装器。

Flask 允许您通过这样的装饰器添加带有参数的路由:

@app.route("meow.com/cat_articles/<int:article_id>")
def show_cat_article(article_id): 
    ...

或者使用 less 神奇地使用 add_url_rule(…)(由装饰器调用)。

def show_cat_article(article_id): 
    ...


app.add_url_rule("meow.com/cat_articles/<int:article_id>", show_cat_article)