带有CherryPy的REST Web服务的友好URL [英] Friendly URL for a REST WebService with CherryPy

查看:37
本文介绍了带有CherryPy的REST Web服务的友好URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用CherryPy 3创建RESTful WebService,但是遇到一个问题:我希望能够回答以下要求:/customers/1/products/386 表示我想要ID为1的客户端的所有ID为386的产品.

所以我尝试使用CherryPy的MethodDispatcher来做到这一点:

  Class UserController(object):暴露=真def __init __():self.product = ProductController()@log_io定义GET(self,* args):返回获取用户:" + str(args)类ProductController(object):暴露=真@log_io定义GET(self,* args):返回获取产品:" + str(args) 

但是,当我请求/customers/1/products/386时,没有使用正确的参数将我重定向到ProductController.GET,而是使用参数1,"products",386将我重定向到UserController.GET.

要重定向到ProductController.GET,我必须查询/customers/products/386,这是不正确的,因为我错过了用户ID参数.

我在此演示文稿上看到过:使用CherryPy的RESTful Web应用程序想要使用似乎是一个不错的选择.但是,有没有一种简单的方法可以用Cherry Py实现它?

我听说过CherryPy 3的_cp_dispatch方法,但我不知道它到底是什么以及如何使用它.它可以代替MethodDispatcher吗?

解决方案

CherryPy使用基于树的映射器,无法很好地适应那些没有物理现实的段作为Python对象,这里是您的/1/段.

话虽如此,CherryPy确实提供了实现您目标的功能.

  • 切换到更明确的映射器,例如选择器

    cherrypy.popargs更直接,因为它为CherryPy否则无法解释的任何段命名.这使段与页面处理程序签名的匹配更加容易,并帮助CherryPy了解您的URL的结构.

     导入cherrypy@ cherrypy.popargs('名称')Band(对象)类:def __init __():self.albums =专辑()@ cherrypy.exposedef索引(自身,名称):返回关于%s ..."的%名称@ cherrypy.popargs('标题')类Album(object):@ cherrypy.exposedef索引(自身,名称,标题):返回关于%s的%s ..."%(标题,名称)如果__name__ =='__main__':cherrypy.quickstart(Band()) 

    在两种情况下,请先访问 http://whatevertomakesohappy.com:8080/nirvana/,然后访问http://whatevertomakesohappy.com:8080/nirvana/albums/nevermind/

    两者都很强大,但是您要使用哪一个取决于您.对于简单的URL,popargs在我的书中可能会容易得多.显然,两者可以同时使用.

    I'm making a RESTful WebService using CherryPy 3 but I encounter a problem : I want to be able to answer requests like : /customers/1/products/386 meaning I want all the product with ID 386 of the client with ID 1.

    So I try to make it with the CherryPy's MethodDispatcher like this :

    class UserController(object):
        exposed = True
    
        def __init__(self):
            self.product = ProductController()
    
        @log_io
        def GET(self, *args):
            return "GET Users :" + str(args)
    
    
    class ProductController(object):
        exposed = True
        @log_io
        def GET(self, *args):
            return "GET Product :" + str(args)
    

    But when I request /customers/1/products/386, instead of redirecting me to ProductController.GET with the right parameters, it redirects me to UserController.GET with the parameters 1, "products", 386.

    To be redirected to ProductController.GET I have to query /customers/products/386 which is incorrect because I miss the user ID parameter.

    I've seen on this presentation : RESTful Web Applications with CherryPy that the path style I want to use seems to be a good choice. But is there an easy way to implement it with Cherry Py ?

    I've heard about the _cp_dispatch method of CherryPy 3 but I don't get exactly what it is and how to use it. Does it replace the MethodDispatcher ?

    解决方案

    CherryPy uses a tree-based mapper which does not accommodate well with segments that have no physical reality as a Python object, here your /1/ segment.

    With that said, CherryPy does provide functionalities to reach your goal.

    • Swap to a more explicit mapper such as selector or routes.
    • Use _cp_dispatch
    • Use cherrypy.popargs

    Let's focus on the last two.

    _cp_dispatch is a special method you declare in any of your controller to massage the remaining segments before CherryPy gets to process them. This offers you the capacity to remove, add or otherwise handle any segment you wish and, even, entirely change the remaining parts.

    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())
    

    cherrypy.popargs is more straightforward as it gives a name to any segment that CherryPy wouldn't be able to interpret otherwise. This makes the matching of segments with page handler signatures easier and help CherryPy understand the structure of your URL.

    import cherrypy
    
    @cherrypy.popargs('name')
    class Band(object):
        def __init__(self):
            self.albums = Album()
    
        @cherrypy.expose
        def index(self, name):
            return 'About %s...' % name
    
    @cherrypy.popargs('title')
    class Album(object):
        @cherrypy.expose
        def index(self, name, title):
            return 'About %s by %s...' % (title, name)
    
    if __name__ == '__main__':
        cherrypy.quickstart(Band())
    

    In both cases go to http://whatevertomakesohappy.com:8080/nirvana/ and then http://whatevertomakesohappy.com:8080/nirvana/albums/nevermind/

    Both are powerful but which one you want to use is up to you. For simple URLs, popargs is likely to be much easier in my book. Obviously both can be used concurrently.

    这篇关于带有CherryPy的REST Web服务的友好URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆