Http verbo decorador para Django?
-
06-07-2019 - |
Pergunta
Em ASP.NET MVC, você pode usar o atributo AcceptVerbs para correlacionar uma função de visualização com um verbo:
public ActionResult Create()
{
// do get stuff
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
// do post stuff
}
O Livro Django sugere algo como isto:
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}),
# ...
)
Isso parece um pouco feio para mim - há um decorador que pode associar um verbo HTTP, com vista, ASP.NET MVC-estilo, ou de outra maneira aceitável de fazer isso
?Solução
Existem padrão built-in decoradores para exigir determinado método HTTP ou lista de métodos permitidos.
Veja o código: http: // código. djangoproject.com/browser/django/trunk/django/views/decorators/http.py .
Outras dicas
resposta Atualizado em 2016: Modern Django tem tudo o necessário embutido e disponível através do vista baseadas em classe . Na forma mais crua, a abordagem canônica é subclasssing django.views.generic.View
e implementação de métodos de classe que são nomeados após o HTTP verbos:
class MyView(View):
def get(self, request, *args, **kwargs):
# ...
def post(self, request, *args, **kwargs):
# ...
Internamente, isso funciona de uma forma muito semelhante ao meu antigo código abaixo (que foi escrito antes Django teve vistas baseadas em classe). Existe um método View.dispatch
que, basicamente, olha o que chamar, ou devolver 405 se não pode encontrar qualquer coisa:. getattr(self, request.method.lower(), self.http_method_not_allowed)
Claro que, se você faz o processamento de formulários, processamento modelo ou coisas CRUD comum, não se esqueça de verificar as subclasses disponíveis View
.
resposta legado a partir de 2009 abaixo. O código ainda funciona em 2016, mas não é uma solução seca, então não usá-lo. Em 2011 Django tem vistas baseadas em classe e hoje eles são a maneira padrão de como as coisas devem ser feitas. Estou mantendo este aqui apenas para fins históricos. texto de resposta de idade seguintes:
Em um ponto de vista particular, onde eu preciso ter código separado para diversos métodos HTTP (esta é a minha pequena aplicação WebDAV), eu estou fazendo algo parecido com isto:
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()),
Adicionado / editado: Bem, eu pensei um pouco e realmente implementado abordagem decorador. Não é tão mau como eu pensava inicialmente.
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'),
Este post é um wiki comunidade, de qualquer maneira, tão à vontade para melhorar se você gosta da idéia! E a história de revisão também contém alguns um pouco diferentes abordagens eu tentei antes de escrever este ...
Você pode usar Ver Decoradores
De docs:
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