DjangoのHTTP動詞デコレータ?
-
06-07-2019 - |
質問
ASP.NET MVCでは、AcceptVerbs属性を使用して、ビュー関数と動詞を関連付けることができます。
public ActionResult Create()
{
// do get stuff
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
// do post stuff
}
Django Book は次のようなものを提案しています:
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:
urlpatterns = patterns('',
# ...
(r'^somepage/
それは少しいようです-HTTP動詞をビュー、ASP.NET MVCスタイル、またはこれを行う他の受け入れられた方法に関連付けることができるデコレータはありますか?
, views.method_splitter, {'GET': views.some_page_get,
'POST': views.some_page_post}),
# ...
)
それは少しいようです-HTTP動詞をビュー、ASP.NET MVCスタイル、またはこれを行う他の受け入れられた方法に関連付けることができるデコレータはありますか?
解決
特定のHTTPメソッドまたは許可されたメソッドのリストを要求するための標準の組み込みデコレータがあります。
コードを参照: http:// code。 djangoproject.com/browser/django/trunk/django/views/decorators/http.py 。
他のヒント
2016年に更新された回答: Modern Djangoには、必要なすべてが組み込まれており、クラスベースのビュー。最も生の形式では、標準的なアプローチは django.views.generic.View
をサブクラス化し、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はクラスベースのビューを取得しましたが、現在ではそれらが物事の標準的な方法です。これは歴史的な目的のためだけにここに保管しています。古い回答テキストは次のとおりです。
HTTPメソッドごとに個別のコードが必要な特定のビュー(これは私の小さなWebDAV実装です)では、次のようなことをしています:
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()),
追加/編集:さて、私は少し考えて、実際にデコレータアプローチを実装しました。当初考えていたほど悪くはありません。
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であるため、アイデアが気に入ったら改善してください!また、改訂履歴には、これを書く前に試した少し異なるアプローチも含まれています...
ドキュメントから:
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