CherryPy 和 RESTful Web API

13 投票
5 回答
19565 浏览
提问于 2025-04-15 22:02

在CherryPy中创建一个RESTful网络API的最佳方法是什么呢?我这几天一直在找,但似乎没有什么特别好的方案。对于Django来说,有很多工具可以做到这一点,但CherryPy似乎没有,或者我还没发现。

后续补充:我应该如何使用CherryPy将像/getOrders?account=X&type=Y这样的请求转换成/orders/account/type这样的形式呢?

5 个回答

2

你想把/getOrders?account=X&type=Y这样的链接变成/orders/account/type,使用Cherrypy来实现。

我建议你参考一下这个链接,正如@Tomasz Blachowicz提到的,稍微做一些修改。

记住,你可以用下面的方式来处理类似/orders/account/type的链接:

@cherrypy.expose
def order(account=None, type=None):
    print account, type

class Root(object):
    pass

root = Root()
root.orders = orders


cherrypy.quickstart(root, '/')

所以,如果你看一下这个链接中的例子,你可以修改它来处理这种类型的URL。

class Orders(object):
    exposed = True
    def __init__(self):
        pass

    def GET(self, account=None, type=None):
        #return the order list for this account type
        return getOrders(account, type)

    def PUT(self, account=None, type=None, orders=None):
        #Set the orders associated with account or something
        setOrders(account, type, orders)


class Root(object):
    pass

root = Root()
root.orders = Orders()

conf = {
    'global': {
        'server.socket_host': '0.0.0.0',
        'server.socket_port': 8000,
    },
    '/': {
        'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
    },
}

cherrypy.quickstart(root, '/', conf)

至于为什么你想用PUT方法来设置订单,我不太清楚,但这确实给了你另一个关于如何使用PUT方法的例子。你只需要把请求中使用的方法换成PUT,它就会调用Orders的PUT()方法,而对Orders使用常规的GET请求时,它会调用GET()方法。因为没有定义POST()方法,所以这个例子不能用POST。如果你尝试使用POST或DELETE,你会收到“405 方法不允许”的错误。

我喜欢这种方法,因为它很容易理解发生了什么,我相信这能解答你的问题。

7

因为HTTP定义了这些调用方法,所以在使用CherryPy实现REST时,最直接的方式是使用MethodDispatcher,而不是默认的调度器。

更多信息可以在CherryPy的文档中找到: http://cherrypy.readthedocs.io/en/latest/tutorials.html#tutorial-7-give-us-a-rest

这里还有关于如何使用CherryPy工具发送和接收JSON的详细说明: http://tools.cherrypy.org/wiki/JSON

11

我不知道这是不是“最佳”方法,但这是我做的方式:

import cherrypy

class RESTResource(object):
   """
   Base class for providing a RESTful interface to a resource.

   To use this class, simply derive a class from it and implement the methods
   you want to support.  The list of possible methods are:
   handle_GET
   handle_PUT
   handle_POST
   handle_DELETE
   """
   @cherrypy.expose
   def default(self, *vpath, **params):
      method = getattr(self, "handle_" + cherrypy.request.method, None)
      if not method:
         methods = [x.replace("handle_", "")
            for x in dir(self) if x.startswith("handle_")]
         cherrypy.response.headers["Allow"] = ",".join(methods)
         raise cherrypy.HTTPError(405, "Method not implemented.")
      return method(*vpath, **params);

class FooResource(RESTResource):
    def handle_GET(self, *vpath, **params):
        retval = "Path Elements:<br/>" + '<br/>'.join(vpath)
        query = ['%s=>%s' % (k,v) for k,v in params.items()]
        retval += "<br/>Query String Elements:<br/>" + \
            '<br/>'.join(query)
        return retval

class Root(object):
    foo = FooResource()

    @cherrypy.expose
    def index(self):
        return "REST example."

cherrypy.quickstart(Root())

你只需要从 RESTResource 类继承,然后处理你想要的 RESTful 请求方式(比如 GET、PUT、POST、DELETE),每种请求方式用一个以 handle_ 开头的方法来处理。如果你没有处理某个请求方式(比如 POST),那么基础类会自动给你抛出一个 405 Method Not Implemented 的错误。

路径中的项目会通过 vpaths 传递,而任何查询字符串则通过 params 传递。根据上面的示例代码,如果你请求 /foo/bar?woo=hoo,那么 vpath[0] 就会是 bar,而 params 的内容会是 {'woo': 'hoo'}

撰写回答