12

URLにPOSTすることは、それをGET、DELETE、またはPUTすることと同じではありません。これらのアクションは根本的に異なります。ただし、Djangoはディスパッチメカニズムでそれらを無視しているようです。基本的に、HTTP動詞を完全に無視するか、すべてのビューでこれを実行する必要があります。

def my_view(request, arg1, arg2):
    if request.method == 'GET':
        return get_view(request, arg1, arg2)
    if request.method == 'POST':
        return post_view(request, arg1, arg2)
    return http.HttpResponseNotAllowed(['GET', 'POST'])

Webでこれについて見つけたいくつかの解決策(動詞ベースのディスパッチのこのスニペット、または動詞要件のこのデコレータ)は、明らかに単なる回避策であるため、あまりエレガントではありません。

CherryPyの状況は同じようです。これを正しく行うために私が知っている唯一のフレームワークは、web.pyとGoogleAppEngineです。

これは、Webフレームワークの重大な設計上の欠陥だと思います。誰か同意しますか?それとも、私が無視する理由/要件に基づいた意図的な決定ですか?

4

4 に答える 4

13

Django について話すことはできませんが、CherryPy では、1 つの構成エントリで HTTP 動詞ごとに 1 つの関数を使用できます。

request.dispatch = cherrypy.dispatch.MethodDispatcher()

ただし、それが望ましくない状況をいくつか見てきました。

一例として、動詞に関係なくハード リダイレクトが挙げられます。

もう 1 つのケースは、ハンドラーの大部分が GET のみを処理する場合です。その場合、すべて 'GET' という名前の 1000 個のページ ハンドラーがあると特に面倒です。関数名よりもデコレータで表現する方がきれいです:

def allow(*methods):
    methods = list(methods)
    if not methods:
        methods = ['GET', 'HEAD']
    elif 'GET' in methods and 'HEAD' not in methods:
        methods.append('HEAD')
    def wrap(f):
        def inner(*args, **kwargs):
            cherrypy.response.headers['Allow'] = ', '.join(methods)
            if cherrypy.request.method not in methods:
                raise cherrypy.HTTPError(405)
            return f(*args, **kwargs):
        inner.exposed = True
        return inner
    return wrap

class Root:
    @allow()
    def index(self):
        return "Hello"

    cowboy_greeting = "Howdy"

    @allow()
    def cowboy(self):
        return self.cowboy_greeting

    @allow('PUT')
    def cowboyup(self, new_greeting=None):
        self.cowboy_greeting = new_greeting

私が目にするもう 1 つの一般的な例は、データベース内のリソースに対応するデータを検索することです。これは、動詞に関係なく発生するはずです。

def default(self, id, **kwargs):
    # 404 if no such beast
    thing = Things.get(id=id)
    if thing is None:
        raise cherrypy.NotFound()

    # ...and now switch on method
    if cherrypy.request.method == 'GET': ...

CherryPy は、ユーザーに代わって決定を下そうとはしませんが、それが必要な場合は簡単 (ワンライナー) にします。

于 2009-08-10T14:22:15.733 に答える
2

django の決定が下されたのは、通常は十分でありGETPOSTフレームワークがその要件に対してよりシンプルに保たれているためだと思います。どの動詞が使われたかを「気にしない」だけでとても便利です。

ただし、動詞に基づいてディスパッチできるフレームワークは他にもたくさんあります。私はwerkzeugが好きです。独自のディスパッチ コードを簡単に定義できるので、必要なものに基づいて、必要なものにディスパッチできます。

于 2009-08-10T12:46:58.937 に答える
1

これはDIYするのは難しくないからです。各クラスの関数に受け入れられた動詞の辞書を用意するだけです。

def dispatcher(someObject, request):
    try:
      return someObject.acceptedVerbs[request.method]()
    except:
      return http.HttpResponseNotAllowed(someObject.acceptedVerbs.keys())
于 2009-08-10T12:58:12.980 に答える