Przyjazny adres URL dla odpoczynku WebService z CherryPy
Robię RESTful WebService używając CherryPy 3 ale napotykam problem : Chcę móc odpowiadać na takie prośby jak : /customers / 1/products / 386 czyli chcę cały produkt o ID 386 Klienta o ID 1.
Więc staram się zrobić to metodą CherryPy ' ego tak:
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)
Ale kiedy żądam /customers/1/products / 386, zamiast przekierowywać mnie do ProductController.Uzyskać odpowiednie parametry, przekierowuje mnie do UserController.GET z parametrami 1, "produkty", 386.
Do przekierowania do ProductController.GET muszę zapytać / klienci/produkty / 386 co jest nieprawidłowe, ponieważ brakuje mi parametru ID użytkownika.
Widziałem na tej prezentacji: RESTful web Applications with CherryPy że styl ścieżki, którego chcę użyć, wydaje się być dobrym wyborem. Ale czy istnieje łatwy sposób na wdrożenie go z Cherry Py ?
Słyszałem o metodzie _cp_dispatch z CherryPy 3 ale nie rozumiem dokładnie co to jest i jak go używać. Czy zastępuje MethodDispatcher ?
2 answers
Cherry używa mapera opartego na drzewie, który nie pasuje do segmentów, które nie mają fizycznej rzeczywistości jako obiekt Pythona, tutaj twój / 1 / segment.
Mając to na uwadze, CherryPy zapewnia funkcjonalności, aby osiągnąć twój cel.
- zamiana na bardziej wyraźny maper, taki jak selektor lub trasy.
- Użyj _cp_dispatch
- Użyj cherrypy.popargs
_cp_dispatch jest specjalną metodą, którą zadeklaruj w dowolnym kontrolerze, aby masować pozostałe segmenty, zanim CherryPy je przetworzy. Dzięki temu możesz usunąć, dodać lub w inny sposób obsłużyć dowolny segment, a nawet całkowicie zmienić pozostałe części.
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 jest prostszy, ponieważ nadaje nazwę każdemu segmentowi, którego CherryPy nie byłby w stanie zinterpretować inaczej. To sprawia, że dopasowanie segmentów z podpisami obsługi strony jest łatwiejsze i pomaga CherryPy zrozumieć struktura adresu 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())
W obu przypadkach przejdź do http://whatevertomakesohappy.com:8080/nirvana / a potem http://whatevertomakesohappy.com:8080/nirvana/albums/nevermind/
Oba są potężne, ale który z nich chcesz użyć, zależy od Ciebie. W przypadku prostych adresów URL popargs prawdopodobnie będzie znacznie łatwiejszy w mojej książce. Oczywiście oba mogą być używane jednocześnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-03 14:24:23
Dzięki za odpowiedź. Doprowadziłeś mnie do odpowiedzi, której szukałem. Ja używałem takiego routera:
self.connect("cust_products", "/customers/{cust_id}/products/",
controller=CustomerController(),
action='index',
conditions=dict(method=['GET']))
self.connect("cust_products", "/customers/{cust_id}/products/{id}",
controller=CustomerController(),
action='show',
conditions=dict(method=['GET']))
self.connect("cust_products", "/customers/{cust_id}/products/",
controller=CustomerController(),
action='create',
conditions=dict(method=['POST']))
self.connect("cust_products", "/customers/{cust_id}/products/{id}",
controller=CustomerController(),
action='update',
conditions=dict(method=['PUT']))
self.connect("cust_products", "/customers/{cust_id}/products/{id}",
controller=CustomerController(),
action='delete',
conditions=dict(method=['DELETE']))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-04 09:10:49