2010-04-26 25 views
12

¿Cuál es el mejor enfoque para crear una API web RESTful en CherryPy? He estado buscando por unos días y nada parece genial. Para Django parece que hay muchas herramientas para hacer esto, pero no para CherryPy o no las conozco.CherryPy y RESTful web api

Más tarde editar: ¿Cómo debo usar CherryPy para transformar una petición como/getOrders representan = X = Y & tipo en algo así como/órdenes/cuenta/tipo?

Respuesta

1

Supongo que ha probado las coincidencias parciales de las que se habló en el tutorial. Me parece que aunque no es genial, hace el trabajo la mayor parte del tiempo.

Más allá de eso, aunque no lo he probado, Cherrypy aparentemente admite Routes (ver http://www.cherrypy.org/wiki/PageHandlers), que le ofrece todo tipo de opciones RESTful.

+0

Enlaces a no trabajar :( –

11

no sé si es la "mejor", pero aquí es cómo lo hago:

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

Simplemente derivados de la clase RESTResource y manejar lo que los verbos REST que desee (GET, PUT, POST, DELETE) con un método del mismo nombre con el prefijo handle_. Si no maneja un verbo en particular (como POST), la clase base generará un error 405 Method Not Implemented.

Los elementos de ruta se pasan en vpaths y las cadenas de consulta se pasan en params. Utilizando el código de ejemplo anterior, si tuviera que solicitar /foo/bar?woo=hoo, vpath[0] sería bar, y params sería {'woo': 'hoo'}.

1

para responder a su segunda pregunta, se quiere definir y exponer un método por defecto:

class getOrders(Object): 
    def default(account, type): 
     ... 

    default.exposed = True 

usando este método, getOrders/x/y se asignaría a default(account='x', type='y'). Como alguien más dijo, no es genial, pero hace el trabajo bien.

En lo que respecta a las aplicaciones RESTful, estoy bastante seguro de que el controlador de página predeterminado funcionará para esa aplicación.

7

Dado que HTTP define estos métodos de invocación, la forma más directa de implementar REST usando CherryPy es utilizar el MethodDispatcher en lugar del dispatcher predeterminado.

más se pueden encontrar en documentos CherryPy: http://cherrypy.readthedocs.io/en/latest/tutorials.html#tutorial-7-give-us-a-rest

Aquí está también la descripción detallada sobre cómo enviar y recibir JSON usando CherryPy Herramientas: http://tools.cherrypy.org/wiki/JSON

+0

El último enlace se ha olvidado. –

2

Así que desea transformar/getOrders? cuenta = X & tipo = Y en algo como/orders/account/type usando Cherrypy.

Me gustaría probar el enfoque utilizado en http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html como lo menciona @Tomasz Blachowicz, con algunas modificaciones.

Recuerde que puede manejar algo como/pedido/cuenta/tipo con

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

class Root(object): 
    pass 

root = Root() 
root.orders = orders 


cherrypy.quickstart(root, '/') 

lo tanto, si se toma el ejemplo dado en http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html, puede modificarlo para manejar ese tipo de 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) 

por las que se desee establecer órdenes que utilizan ese método put No sé, pero nos da otro ejemplo de cómo no poner métodos. Todo lo que tienes que hacer es reemplazar el método utilizado por una solicitud con PUT y usará el método PUT() de Órdenes y usar un GET regular en Órdenes y usará el método GET(). Como el método POST() no está definido, POST no se puede usar con este ejemplo. Si prueba POST o ELIMINAR obtendrá "405 Method Not Allowed".

Me gusta este enfoque porque es fácil ver lo que está pasando y, creo, responde a su pregunta.