POST 到 URL 与 GET、DELETE 或 PUT 不同。这些 Action 是根本不同的。然而,Django 似乎在其调度机制中忽略了它们。基本上,人们被迫要么完全忽略 HTTP 动词,要么在每个 View 上都这样做:
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 的。
我认为这是网络框架的严重设计缺陷。有人同意吗?还是基于我忽略的原因/要求而故意做出的决定?
最佳答案
我不能代表 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 试图不为您做出决定,但如果您想要的话,它会让它变得简单(单行)。
关于python - 为什么 Django 和 CherryPy 本身不支持基于 HTTP 动词的调度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1254629/