POST到URL不同于获取它,删除它或将其删除。这些行为从根本上是不同的。但是,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'])
我在网上找到的几个解决方案(this snippet用于基于动词的调度,或this decorator用于动词要求)不是很优雅,因为它们显然只是解决方法。
CherryPy的情况似乎是一样的。我所知道的唯一能够做到这一点的框架是web.py和Google App Engine。
我认为这是Web框架的严重设计缺陷。有人同意吗?或者这是基于我忽略的原因/要求的故意决定?
答案 0 :(得分:13)
我不能代表Django,但在CherryPy中,每个HTTP动词只有一个配置项可以有一个函数:
request.dispatch = cherrypy.dispatch.MethodDispatcher()
但是,我已经看到了一些不可取的情况。
一个例子是硬重定向而不管动词。
另一种情况是大多数处理程序只处理GET。在这种情况下,有一千个名为'GET'的页面处理程序尤其令人讨厌。在装饰器中表达它比在函数名称中更漂亮:
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
我看到的另一个常见问题是查找与数据库中的资源相对应的数据,无论动词如何都应该这样做:
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试图不为你做出决定,但如果这就是你想要的话,那就很容易(单行)。
答案 1 :(得分:6)
来自Google,想到了更新。
仅供参考,Django现在支持基于类的视图。您可以扩展通用类View
并添加get()
,post()
,put()
等方法。 -
from django.http import HttpResponse
from django.views.generic import View
class MyView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
dispatch()
部分处理此 -
发送(请求,* args,** kwargs)
视图的视图部分 - 接受请求参数加参数的方法,并返回一个 HTTP响应。
默认实现将检查HTTP方法并尝试 委托给匹配HTTP方法的方法; GET将是 委托给get(),POST到post()等等。
默认情况下,HEAD请求将委派给get()。如果你需要 以与GET不同的方式处理HEAD请求,您可以覆盖 head()方法。有关示例,请参阅支持其他HTTP方法。
默认实现还将request,args和kwargs设置为 实例变量,因此视图上的任何方法都可以知道完整 用于调用视图的请求的详细信息。
然后您可以在urls.py
-
from django.conf.urls import patterns, url
from myapp.views import MyView
urlpatterns = patterns('',
url(r'^mine/$', MyView.as_view(), name='my-view'),
)
CherryPy现在也支持这一点。他们对此有full page。
答案 2 :(得分:2)
我认为django的决定是因为通常只有GET
和POST
就足够了,这使得框架的要求更加简单。 “不关心”使用哪个动词非常方便。
但是,还有很多其他框架可以根据动词进行调度。我喜欢werkzeug,它可以很容易地定义您自己的调度代码,因此您可以根据自己想要的任何内容发送任何内容。
答案 3 :(得分:1)
因为这不难DIY。只需在每个班级都有一个接受动词的词典。
def dispatcher(someObject, request):
try:
return someObject.acceptedVerbs[request.method]()
except:
return http.HttpResponseNotAllowed(someObject.acceptedVerbs.keys())