5

在 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

网址.py:

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

这对我来说似乎有点难看 - 是否有一个装饰器可以将 HTTP 动词与视图、ASP.NET MVC 样式或其他公认的方式相关联?

4

3 回答 3

11

有标准的内置装饰器用于要求特定的 HTTP 方法或允许的方法列表。

查看代码:http ://code.djangoproject.com/browser/django/trunk/django/views/decorators/http.py 。

于 2009-06-19T05:53:49.140 回答
9

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'),

无论如何,这篇文章是一个社区维基,所以如果你喜欢这个想法,请随时改进!并且修订历史还包含一些我在写这篇文章之前尝试过的一些不同的方法......

于 2009-06-18T16:24:03.400 回答
3

您可以使用视图装饰器

从文档:

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
于 2012-03-01T21:53:09.313 回答