2009-06-18 12 views
5

In ASP.NET MVC, können Sie die AcceptVerbs verwenden Attribut einen View-Funktion mit einem Verb korrelieren:Http Verb Dekorator für Django?

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

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

The Django Book schlägt vor, etwa wie folgt:

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}), 
    # ... 
) 

Das scheint ein bisschen hässlich für mich - gibt es einen Dekorator, der ein HTTP-Verb mit einer Ansicht, ASP.NET MVC-Stil oder einem anderen Akzeptieren assoziieren kann d Möglichkeit dies zu tun?

Antwort

11

Es gibt standardmäßige eingebaute Dekoratoren für bestimmte HTTP-Methode oder Liste der zulässigen Methoden.

Siehe den Code: http://code.djangoproject.com/browser/django/trunk/django/views/decorators/http.py.

+0

Dies ist in der Tat der Weg, es zu tun. Beachten Sie, dass es dort auch einen Decorator-Generator gibt, mit dem Sie Dekoratoren für beliebige Kombinationen von Methoden erstellen können. (und ich habe keine Ahnung, warum Sie downvoted für die offensichtliche und richtige Antwort auf die Frage ...) –

+3

Ich glaube, das ist nicht die richtige Antwort, weil require_http_methods() ist ein Filter, nicht Dispatcher. Man kann @require_http_methods ("GET") nicht für eine Funktion verwenden, @require_http_methods ("POST") für eine andere (mit demselben Namen!), Und Django sollte die richtige Methode wählen, um nach Methodenverb zu rufen. – drdaeman

9

Aktualisierte Antwort im Jahr 2016: Moderne Django hat alles Notwendige eingebaut und verfügbar durch die class-based views. In dem am meisten Rohform, ist der kanonische Ansatz django.views.generic.View und Implementierung von Klassenmethoden subclasssing, die nach den HTTP-Verben benannt sind:

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

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

Intern dies in einer Art und Weise zu meinem alten Code sehr ähnlich funktioniert unten (die zuvor geschrieben wurden Django hatte klassenbasierte Ansichten. Es gibt eine View.dispatch Methode, die im Grunde nachschaut was zu rufen ist, oder 405 zurückgibt, wenn sie nichts findet: getattr(self, request.method.lower(), self.http_method_not_allowed).

Natürlich, wenn Sie Formularverarbeitung, Vorlage-Rendering oder allgemeine CRUD-Zeug machen, achten Sie darauf, die verfügbaren View Unterklassen zu überprüfen.


Legacy-Antwort von 2009 unten. Der Code funktioniert noch 2016, ist aber keine DRY-Lösung, also verwenden Sie ihn nicht. Im Jahr 2011 bekam Django klassenbasierte Ansichten und heutzutage sind sie die Standardmethode, wie Dinge gemacht werden sollten. Ich halte das hier nur für historische Zwecke. Alter Antworttext folgt:

In einem besonderen Blick, wo ich separaten Code für verschiedene HTTP-Methoden haben muß (dies ist meine kleine WebDAV-Implementierung), ich tue etwas wie folgen aus:

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

Added/edited: Nun, ich habe ein bisschen nachgedacht und tatsächlich Decorator Ansatz implementiert. Es ist nicht so schlimm, wie ich anfangs dachte.

Dieser Beitrag ist ein Community-Wiki, wie auch immer, also fühlen Sie sich frei, zu verbessern, wenn Sie die Idee mögen! Und die Revisionshistorie enthält auch ein paar andere Ansätze, die ich versuchte, bevor ich dies schreibe ...

+1

Beachten Sie, dass in den meisten Form Verarbeitungs Arbeit, die Sie wahrscheinlich nicht wirklich trennen wollen GET und POST-Methoden, weil Sie wahrscheinlich gehen um eine Seite zurückzugeben, die ein Formular mit Fehlern bei fehlgeschlagenem POST enthält. – drdaeman

+0

Gute Arbeit - schrieb eine ähnliche Lösung, als ich deine Antwort sah. Sie haben es geschafft, zu einem eleganteren Ergebnis zu kommen;) –

+0

Danke. Tatsächlich gibt es eine Menge zu verbessern - derzeitiger Code versucht nicht einmal, Attribute zu erhalten (wie __doc__ oder __name__) und nicht wirklich fehleranfällig (zum Beispiel gibt es überhaupt keine Signaturprüfung). Ich habe über Dekorator-Modul (http://pypi.python.org/pypi/decorator) nachgedacht, aber ich bin zu faul;) – drdaeman

3

können Sie verwenden View Decorators

Aus der Dokumentation:

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 
Verwandte Themen