Подтвердить что ты не робот

CherryPy и RESTful web api

Каков наилучший подход к созданию веб-страницы RESTful в CherryPy? Я смотрю вокруг уже несколько дней, и ничего не кажется большим. Для Django кажется, что для этого есть множество инструментов, но не для CherryPy, или я не знаю о них.

Позже отредактируйте: Как использовать Cherrypy для преобразования запроса типа /getOrders? account = X & type = Y в нечто вроде/orders/account/type?

4b9b3361

Ответ 1

Я не знаю, является ли это "лучшим" способом, но вот как я это делаю:

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'}.

Ответ 2

Поскольку HTTP определяет эти методы вызова, самый прямой способ реализовать REST с использованием CherryPy - использовать MethodDispatcher вместо диспетчера по умолчанию.

Подробнее можно найти в документах CherryPy: http://cherrypy.readthedocs.io/en/latest/tutorials.html#tutorial-7-give-us-a-rest

Вот также подробное описание того, как отправлять и получать JSON с помощью инструментов CherryPy: http://tools.cherrypy.org/wiki/JSON

Ответ 3

Итак, вы хотите преобразовать /getOrders? account = X & type = Y в нечто вроде /orders/account/type с помощью Cherrypy.

Я бы попытался использовать метод http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html, как упоминал @Tomasz Blachowicz, с некоторыми изменениями.

Помните, что вы можете обрабатывать что-то вроде /order/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, '/')

Итак, если вы примете пример, приведенный в http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html, вы можете изменить его для обработки этого типа 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, и будет использовать метод PUT() Orders и использовать регулярное GET на Orders, и он будет использовать метод GET(). Поскольку метод POST() не определен, POST не может использоваться с этим примером. Если вы попробуете POST или DELETE, вы получите "405 Method Not Allowed".

Мне нравится этот подход, потому что легко понять, что происходит, и, я считаю, он отвечает на ваш вопрос.

Ответ 4

Я предполагаю, что вы пробовали частичные совпадения, о которых говорилось в учебнике. Я нахожу, что, хотя это и не очень хорошо, он выполняет большую часть времени.

Помимо этого, хотя я и не пробовал, Cherrypy, по-видимому, поддерживает Routes (см. http://www.cherrypy.org/wiki/PageHandlers), который предоставляет вам все варианты RESTful.

Ответ 5

Чтобы ответить на второй вопрос, вы хотите определить и выставить метод по умолчанию:

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

    default.exposed = True

используя этот метод, getOrders/x/y будет отображаться в default(account='x', type='y'). Как и кто-то другой, это не здорово, но он выполняет свою работу.

Что касается приложений RESTful, я уверен, что обработчик страницы по умолчанию будет работать для такого приложения.