我如何根据 CherryPy 中请求的 URL 显示任意页面?

How can I show arbitrary pages based oy the URL requested in CherryPy?

例如,如果用户要转到 localhost:8080/foobar228,我不需要通过定义函数在 foobar228 页面的请求中进行硬编码。我只想有一个函数,它可以为您提供请求的 URL ("foobar228") 和其他信息,例如 GET 和 POST 请求,以及 returns 和 HTML 到被送达。有什么办法吗?

特殊的_cp_dispatch方法

_cp_dispatch 是您在任何控制器中声明的一种特殊方法,用于在 CherryPy 开始处理剩余部分之前处理它们。这使您能够删除、添加或以其他方式处理您想要的任何部分,甚至可以完全更改其余部分。

import cherrypy

class Band(object):
    def __init__(self):
        self.albums = Album()

    def _cp_dispatch(self, vpath):
        if len(vpath) == 1:
            cherrypy.request.params['name'] = vpath.pop()
            return self

        if len(vpath) == 3:
            cherrypy.request.params['artist'] = vpath.pop(0)  # /band name/
            vpath.pop(0) # /albums/
            cherrypy.request.params['title'] = vpath.pop(0) # /album title/
            return self.albums

        return vpath

    @cherrypy.expose
    def index(self, name):
        return 'About %s...' % name

class Album(object):
    @cherrypy.expose
    def index(self, artist, title):
        return 'About %s by %s...' % (title, artist)

if __name__ == '__main__':
    cherrypy.quickstart(Band())

请注意控制器如何定义 _cp_dispatch,它采用单个参数,URL 路径信息分成多个部分。

该方法可以检查和操作段列表,在任何位置删除任何段或添加新段。然后将新的段列表发送到调度程序,调度程序将使用它来定位适当的资源。

在上面的示例中,您应该可以转到以下 URLs:

http://localhost:8080/nirvana/

http://localhost:8080/nirvana/albums/nevermind/

/nirvana/ 片段与乐队相关,/nevermind/ 片段与专辑相关。

为了实现这一点,我们的 _cp_dispatch 方法基于这样的想法,即默认调度程序将 URLs 与页面处理程序签名及其在处理程序树中的位置相匹配。

取自docs

使用默认方法。这是一个例子。

import cherrypy


class Root:

    @cherrypy.expose
    def default(self, *url_parts, **params):
        req = cherrypy.request
        print(url_parts)
        body = [
            'Page served with method: %s' % req.method,
            'Query string from req: %s' % req.query_string,
            'Path info from req: %s' % req.path_info,
            'Params (query string + body for POST): %s' % params,
            'Body params (only for POST ): %s' % req.body.params
        ]
        if url_parts: # url_parts is path_info but divided by "/" as a tuple
            if url_parts[0] == 'foobar228':
                body.append( 'Special foobar page')
            else:
                body.append('Page for %s' % '/'.join(url_parts))
        else:
            body.append("No path, regular page")
        return '<br>\n'.join(body)

cherrypy.quickstart(Root())

url 段成为位置参数,任何查询字符串 (?foo=bar) 都是该方法的关键字参数的一部分,POST 方法的正文参数也是包含在关键字参数中(在这种情况下,在方法定义中的名称 params 下。