Обновленный ответ в 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'),
Этот пост, в любом случае, является вики сообщества, так что не стесняйтесь улучшать его, если вам нравится идея! И история ревизий также содержит несколько разные подходы, которые я пробовал перед написанием этого ...