2013-04-03 39 views
14

Tôi đang thực hiện một WebService RESTful sử dụng CherryPy 3 nhưng tôi gặp phải một vấn đề REST: Tôi muốn để có thể trả lời các yêu cầu như: /khách hàng/1/products/386 ý nghĩa tôi muốn tất cả các sản phẩm với ID 386 của khách hàng với ID 1.URL thân thiện cho một WebService với CherryPy

Vì vậy, tôi cố gắng để làm cho nó với MethodDispatcher của CherryPy như thế này:

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) 

Nhưng khi tôi yêu cầu/khách hàng/1/products/386, thay vì chuyển hướng tôi đến ProductController.GET với mệnh đề đúng ters, nó chuyển hướng tôi đến UserController.GET với các tham số 1, "sản phẩm", 386.

Để được chuyển hướng đến ProductController.GET Tôi phải truy vấn/khách hàng/sản phẩm/386 không chính xác vì tôi nhớ ID người dùng tham số.

Tôi đã xem trên bản trình bày này: RESTful Web Applications with CherryPy rằng kiểu đường dẫn tôi muốn sử dụng có vẻ là lựa chọn tốt. Nhưng có cách nào dễ dàng để thực hiện nó với Cherry Py?

Tôi đã nghe về phương pháp _cp_dispatch của CherryPy 3 nhưng tôi không hiểu chính xác nó là gì và cách sử dụng nó. Nó có thay thế MethodDispatcher không?

Trả lời

20

CherryPy sử dụng trình lập bản đồ dựa trên cây không phù hợp với các phân đoạn không có thực tế vật lý như đối tượng Python, tại đây/1/phân đoạn của bạn.

Với điều đó đã nói, CherryPy cung cấp các chức năng để đạt được mục tiêu của bạn.

  • Trao đổi với người lập bản đồ rõ ràng hơn như selector hoặc routes.
  • Sử dụng _cp_dispatch
  • Sử dụng cherrypy.popargs

Hãy tập trung vào hai vừa qua.

_cp_dispatch là một phương pháp đặc biệt mà bạn khai báo trong bất kỳ bộ điều khiển nào của bạn để xoa bóp các phân đoạn còn lại trước khi CherryPy xử lý chúng. Điều này cung cấp cho bạn khả năng loại bỏ, thêm hoặc xử lý bất kỳ phân đoạn nào bạn muốn và thậm chí thay đổi hoàn toàn các phần còn lại.

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 đơn giản hơn vì nó cung cấp tên cho bất kỳ phân đoạn nào mà CherryPy không thể giải thích khác được. Điều này làm cho việc kết hợp các phân đoạn với các ký hiệu xử lý trang dễ dàng hơn và giúp CherryPy hiểu cấu trúc của URL của bạn.

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

Trong cả hai trường hợp đi đến http://whatevertomakesohappy.com:8080/nirvana/ và sau đó http://whatevertomakesohappy.com:8080/nirvana/albums/nevermind/

Cả hai đều mạnh mẽ nhưng cái nào bạn muốn sử dụng là tùy thuộc vào bạn. Đối với các URL đơn giản, popargs có thể dễ dàng hơn nhiều trong cuốn sách của tôi. Rõ ràng cả hai có thể được sử dụng đồng thời.

4

Cảm ơn câu trả lời của bạn Sylvain. Bạn đã dẫn tôi đến câu trả lời tôi đang tìm kiếm. Tôi đã sử dụng RouteDispatcher như thế này:

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'])) 
Các vấn đề liên quan