Http глагол декоратор для Джанго? - PullRequest
5 голосов
/ 18 июня 2009

В ASP.NET MVC вы можете использовать атрибут AcceptVerbs, чтобы соотнести функцию представления с глаголом:

public ActionResult Create()
{
    // do get stuff
} 

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
    // do post stuff
}

Книга Джанго предлагает что-то вроде этого:

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/$', views.method_splitter, {'GET': views.some_page_get, 
        'POST': views.some_page_post}),
    # ...
)

Это кажется мне немного уродливым - есть ли декоратор, который может связать HTTP-глагол с представлением, ASP.NET MVC-стиль или другой приемлемый способ сделать это?

Ответы [ 3 ]

11 голосов
/ 19 июня 2009

Существуют стандартные встроенные декораторы для запроса определенного метода HTTP или списка разрешенных методов.

См. Код: http://code.djangoproject.com/browser/django/trunk/django/views/decorators/http.py.

9 голосов
/ 18 июня 2009

Обновленный ответ в 2016 году: В современном Django есть все необходимое, встроенное и доступное через классовые представления . В наиболее сырой форме канонический подход - это подкласс django.views.generic.View и реализация методов класса, которые названы в честь глаголов HTTP:

class MyView(View):
    def get(self, request, *args, **kwargs):
        # ...

    def post(self, request, *args, **kwargs):
        # ...

Внутренне, это работает способом, очень похожим на мой древний код ниже (который был написан до того, как у Джанго были представления на основе классов). Существует метод View.dispatch, который в основном ищет, что вызвать, или возвращает 405, если ничего не может найти: getattr(self, request.method.lower(), self.http_method_not_allowed).

Конечно, если вы выполняете обработку форм, рендеринг шаблонов или обычные вещи CRUD, обязательно ознакомьтесь с доступными подклассами View.


Устаревший ответ от 2009 года ниже. Код все еще работает в 2016 году, но не является СУХИМЫМ решением, поэтому не используйте его. В 2011 году Джанго получил взгляды на основе классов, и в настоящее время они являются стандартным способом, которым все должно быть сделано. Я держу это здесь исключительно в исторических целях. Старый текст ответа следует:

В одном конкретном представлении, где мне нужен отдельный код для разных методов 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'),

Этот пост, в любом случае, является вики сообщества, так что не стесняйтесь улучшать его, если вам нравится идея! И история ревизий также содержит несколько разные подходы, которые я пробовал перед написанием этого ...

3 голосов
/ 02 марта 2012

Вы можете использовать Просмотр декораторов

Из документов:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...