Risposta aggiornata nel 2016: Modern Django ha tutto il necessario integrato e disponibile tramite class-based views. Nella forma più grezza, l'approccio canonico è subclasssing django.views.generic.View
e l'attuazione di metodi di classe che prendono il nome i verbi HTTP:
class MyView(View):
def get(self, request, *args, **kwargs):
# ...
def post(self, request, *args, **kwargs):
# ...
Internamente, questo funziona in modo molto simile al mio antico codice qui sotto (che è stato scritto prima Django aveva viste basate sulla classe). C'è un metodo View.dispatch
che fondamentalmente cerca cosa chiamare, o restituisce 405 se non riesce a trovare nulla: getattr(self, request.method.lower(), self.http_method_not_allowed)
.
Ovviamente, se si esegue l'elaborazione dei moduli, il rendering dei modelli o roba CRUD comune, assicurarsi di verificare le sottoclassi disponibili View
.
Legacy risposta a partire dal 2009 sotto. Il codice funziona ancora nel 2016, ma non è una soluzione DRY, quindi non utilizzarlo. Nel 2011 Django ha ottenuto visualizzazioni basate su classi e al giorno d'oggi sono il modo standard in cui le cose dovrebbero essere fatte. Sto mantenendo questo qui solo per scopi storici. Vecchio risposta testo segue:
In una particolare visione in cui ho bisogno di avere codice separato per i diversi metodi HTTP (questo è il mio piccolo implementazione WebDAV), sto facendo qualcosa di simile:
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()),
Aggiunto/modificato: Bene, ho pensato un po 'e in realtà implementato approccio decoratore. Non è così male come inizialmente pensavo.
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'),
Questo post è un wiki comunità, in ogni caso, quindi sentitevi liberi di migliorare se vi piace l'idea! E la cronologia delle revisioni contiene anche alcuni approcci un po 'diversi che ho provato prima di scrivere questo ...
Questo è davvero il modo di farlo. Nota che c'è anche un generatore di decoratore che ti permette di creare decoratori per qualsiasi combinazione di metodi che ti piacciono. (e non ho idea del perché sei stato downvoted per dare la risposta ovvia e corretta alla domanda ...) –
Credo che questa non è la risposta corretta, perché require_http_methods() è un filtro, non dispatcher. Non si può fare @require_http_methods ("GET") per una funzione, @require_http_methods ("POST") per un'altra (con lo stesso nome!), E lasciare che Django scelga la giusta da chiamare per metodo verb. – drdaeman