2016 年更新的答案:现代 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'),
无论如何,这篇文章是一个社区维基,所以如果你喜欢这个想法,请随时改进!并且修订历史还包含一些我在写这篇文章之前尝试过的一些不同的方法......