CherryPyでRESTful Web APIを作成する最良の方法は何ですか? 私は数日間見回してきましたが、何も素晴らしいようには見えません。Djangoの場合、これを行うためのツールがたくさんあるようですが、CherryPyの場合はそうではないか、私はそれらを認識していません。
後で編集: Cherrypy を使用して /getOrders?account=X&type=Y のようなリクエストを /orders/account/type のようなものに変換するにはどうすればよいですか?
それが「最善」の方法かどうかはわかりませんが、次のようにします。
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'}
。
HTTP はこれらの呼び出しメソッドを定義するため、CherryPy を使用して REST を実装する最も直接的な方法は、デフォルトのディスパッチャーの代わりに MethodDispatcher を利用することです。
詳細は CherryPy ドキュメントにあります: http://cherrypy.readthedocs.io/en/latest/tutorials.html#tutorial-7-give-us-a-rest
CherryPy ツールを使用して JSON を送受信する方法の詳細な説明もここにあります: http://tools.cherrypy.org/wiki/JSON
したがって、Cherrypy を使用して /getOrders?account=X&type=Y を /orders/account/type のようなものに変換する必要があります。
@Tomasz Blachowicz で言及されているhttp://cherrypy.readthedocs.org/en/latest/tutorial/REST.htmlで使用されているアプローチをいくつか変更して試してみます。
/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 に置き換えるだけで、Orders の PUT() メソッドが使用され、Orders で通常の GET が使用され、GET() メソッドが使用されます。POST() メソッドが定義されていないため、この例では POST を使用できません。POST または DELETE を試みると、「405 Method Not Allowed」が表示されます。
何が起こっているのかを簡単に確認でき、あなたの質問に答えてくれると信じているので、私はこのアプローチが好きです。
2 番目の質問に答えるには、デフォルト メソッドを定義して公開します。
class getOrders(Object):
def default(account, type):
...
default.exposed = True
このメソッドを使用すると、getOrders/x/y は にマップされdefault(account='x', type='y')
ます。他の誰かが言ったように、それは素晴らしいことではありませんが、仕事を成し遂げます.
RESTful アプリケーションに関する限り、デフォルトのページ ハンドラーがそのようなアプリケーションで機能すると確信しています。
I assume you've tried partial matches as talked about in the tutorial. I find that while not great, it does get the job done most of the time.
Beyond that, though I haven't tried it, Cherrypy apparently supports Routes (see http://www.cherrypy.org/wiki/PageHandlers), which gives you all kinds of RESTful options.