2009-06-18 11 views
5

、あなたはAcceptVerbsを使用することができ動詞でビュー機能を相関させる属性:DjangoのHttp動詞デコレータ? ASP.NET MVCで

def method_splitter(request, *args, **kwargs): 
    get_view = kwargs.pop('GET', None) 
    post_view = kwargs.pop('POST', None) 
    if request.method == 'GET' and get_view is not None: 
     return get_view(request, *args, **kwargs) 
    elif request.method == 'POST' and post_view is not None: 
     return post_view(request, *args, **kwargs) 
    raise Http404 

はurls.py:

public ActionResult Create() 
{ 
    // do get stuff 
} 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create(FormCollection collection) 
{ 
    // do post stuff 
} 

The Django Bookはこのようなものを提案しています

urlpatterns = patterns('', 
    # ... 
    (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 
     'POST': views.some_page_post}), 
    # ... 
) 

これはちょっと醜いようです - HTTP動詞をビュー、ASP.NET MVCスタイル、または他の受け入れに関連付けることができるデコレータがありますかこれを行う方法は?

答えて

11

特定のHTTPメソッドまたは許可されたメソッドのリストを要求する標準の組み込みデコレータがあります。

コード:http://code.djangoproject.com/browser/django/trunk/django/views/decorators/http.pyを参照してください。

+0

これは本当にそれを行う方法です。そこにはデコレータジェネレータもありますので、好きなメソッドの組み合わせに合わせてデコレータを作成することができます。 (なぜ私はあなたが質問に明白で正しい答えを与えるためにdownvotedを得たのかわかりません) –

+3

require_http_methods()はフィルタでありディスパッチャではないので、これは正解ではないと私は信じています。ある関数の@require_http_methods( "GET")、別のもの(@同じ名前の!)の@require_http_methods( "POST")を実行することはできず、Djangoはメソッド動詞で呼び出す適切なものを選択させます。 – drdaeman

9

最新の2016年の回答:現代のDjangoには、必要なものがすべて組み込まれており、class-based viewsから入手できます。ほとんどの生の形式では、標準的なアプローチはdjango.views.generic.ViewをsubclasssingとHTTP動詞にちなんで命名されたクラスのメソッド実装されています。内部

class MyView(View): 
    def get(self, request, *args, **kwargs): 
     # ... 

    def post(self, request, *args, **kwargs): 
     # ... 

を、これは以前に書かれていた(以下の私の古代のコードと非常によく似た方法で動作しますDjangoにはクラスベースのビューがありました)。基本的に何を呼び出すかを調べるView.dispatchメソッドがあります。何も見つからない場合は405を返します。getattr(self, request.method.lower(), self.http_method_not_allowed)

もちろん、フォーム処理、テンプレートレンダリング、一般的なCRUDなどを行う場合は、利用可能なViewサブクラスを確認してください。


以下の2009年のレガシー回答。コードはまだ2016年に動作しますが、DRYソリューションではありませんので、使用しないでください。 2011年にDjangoはクラスベースのビューを取得しましたが、現在では、これらのメソッドを標準的な方法で実行する必要があります。私は歴史的な目的のためだけにこれを保管しています。旧解答テキストは、次のとおりです。

class SomeView(object): 
    def method_get(self, request, ...): 
     ... 

    def __call__(self, request, *args, **kwargs): 
     m = getattr(self, 'method_%s' % request.method.lower(), None) 
     if m is not None: 
      return m(request, user, *args, **kwargs) 
     return HttpResponseNotAllowed("405 Method Not Allowed") 

# Then url(r'...', SomeView()), 

を追加しました:

を私は別のHTTPメソッド用に別のコードを持っている必要がある1つの特定のビューでは(これは私の小さなWebDAV実装である)、私はこのような何かをやっています/編集:まあ、私は少し考えて、実際にデコレータのアプローチを実装しました。私が最初に思ったほど悪くはありません。

def method_not_allowed_view(request, *args, **kwargs): 
    return HttpResponseNotAllowed("405 Method Not Allowed") 

def http_method(*methods): 
    methods = map(lambda m: m.lower(), methods) 
    def __method_wrapper(f): 
     this_module = __import__(__name__) 
     chain = getattr(this_module, f.__name__, method_not_allowed_view) 
     base_view_func = lambda request, *args, **kwargs: \ 
      f(request, *args, **kwargs) if request.method.lower() in methods \ 
             else chain(request, *args, **kwargs) 
     setattr(this_module, f.__name__, base_view_func) 
     return base_view_func 
    return __method_wrapper 

@http_method('get') 
def my_view(request): 
    return HttpResponse("Thank you for GETting.") 

@http_method('post', 'put') 
def my_view(request): 
    return HttpResponse("Thank you for POSTing or PUTting.") 

# url(r'...', 'app.my_view'), 

この投稿は、とにかくコミュニティのwikiですので、気に入ったら改善してください!また、改訂履歴には、これを書く前に試してみた少し異なるアプローチが含まれています...

+1

注意を、失敗したPOSTでエラーのあるフォームを含むページを返す。 – drdaeman

+0

私はあなたの答えを見たときに、素晴らしい仕事 - 同様の解決策を書いていました。あなたはより洗練された結果に到達することができましたが); –

+0

ありがとうございました。実際には、現在のコードでは属性(__doc__や__name__など)を保持しようとせず、実際にはエラーが発生しにくい(たとえば、シグネチャのチェックは全く行われません)ようにもなりません。私はデコレータモジュール(http://pypi.python.org/pypi/decorator)を使うことを考えていましたが、私はあまりにも怠惰です; – drdaeman

3

あなたはドキュメントからView Decorators

を使用することができます:あなたはおそらく行っているため、ほとんどのフォーム処理作業中に、あなたは、おそらく実際には、GETとPOSTメソッドを分離したくないことを

from django.views.decorators.http import require_http_methods 

@require_http_methods(["GET", "POST"]) 
def my_view(request): 
    # I can assume now that only GET or POST requests make it this far 
    # ... 
    pass 
関連する問題