Klassenansichten in Django

stimmen
48

Django Ansicht zeigt auf eine Funktion, die ein Problem sein kann , wenn man nur ein wenig Funktionalität ändern möchten. Ja, ich könnte Millionen Schlüsselwort Argumente haben und noch mehr , wenn Aussagen in der Funktion, aber ich war mehr von einem objektorientierten Ansatz zu denken.

Zum Beispiel habe ich eine Seite, die einen Benutzer anzeigt. Diese Seite ist sehr ähnlich zu Seite, die eine Gruppe zeigt, aber es ist noch nicht so ähnlich, nur ein anderes Datenmodell zu verwenden. Gruppe hat auch Mitglieder etc ...

Eine Möglichkeit wäre, Blick auf Klassenmethoden zu zeigen und dann diese Klasse zu erweitern. Hat jemand diesen Ansatz versucht oder hat andere Idee?

Veröffentlicht am 03/08/2008 um 16:55
quelle vom benutzer
In anderen Sprachen...                            


9 antworten

stimmen
41

Ich habe meine eigene allgemeine Ansicht Klassen erstellt und verwendet wird , definieren __call__so eine Instanz der Klasse ist aufrufbar. Ich mag es wirklich; während Djangos allgemeine Ansichten einigen Anpassungen durch Keyword - Argumente, OO allgemeine Ansichten können (wenn ihr Verhalten in eine Anzahl von separaten Methoden aufgeteilt wird) viele feinkörnige Anpassung über Subclassing haben , die mich selbst weniger viel lassen wiederholen. (Ich müde Umschreiben der gleichen erstellen / aktualisieren Ansicht Logik jederzeit Ich brauche etwas Djangos allgemeine Ansichten zwicken nicht ganz lassen).

Ich habe einige Code im Internet abrufbar djangosnippets.org .

Der einzige wirkliche Nachteil ich sehe, ist die Verbreitung von internen Methodenaufrufe, die die Leistung etwas beeinflussen können. Ich glaube nicht, das viel von einer Besorgnis ist; es ist selten, dass Python Code-Ausführung Ihre Performance-Engpass in einem Web-App sei.

UPDATE : Django eigene generische Ansichten sind nun klassenbasierte.

UPDATE : FWIW, ich habe meine Meinung über klassenbasierte Ansichten geändert , da diese Antwort geschrieben wurde. Nachdem sie auf ein paar Projekte ausgiebig genutzt haben, fühle ich sie zu Code führen dazu neigen , die satisfyingly DRY ist zu schreiben, aber sehr schwer zu lesen und später beibehalten, weil Funktionalität über so viele verschiedene Orte verteilt ist, und Unterklassen sind so abhängig bei jeder Implementierung Detail der Oberklassen und Mixins. Ich fühle mich jetzt , dass TemplateResponse und Dekorateure Ansicht ist eine bessere Antwort für die Code - Ansicht zersetzen.

Beantwortet am 29/08/2008 um 05:29
quelle vom benutzer

stimmen
13

Ich brauchte Klasse basierte Ansichten zu verwenden, aber ich wollte, ohne immer mit den vollständigen Namen der Klasse in meinem URLconf zu verwenden, um die Lage sein, die Ansichtsklasse instanziiert, bevor es zu benutzen. Was hat mir geholfen, war eine überraschend einfache metaclass:

class CallableViewClass(type):
    def __call__(cls, *args, **kwargs):
        if args and isinstance(args[0], HttpRequest):
            instance = super(CallableViewClass, cls).__call__()
            return instance.__call__(*args, **kwargs)
        else:
            instance = super(CallableViewClass, cls).__call__(*args, **kwargs)
            return instance


class View(object):
    __metaclass__ = CallableViewClass

    def __call__(self, request, *args, **kwargs):
        if hasattr(self, request.method):
            handler = getattr(self, request.method)
            if hasattr(handler, '__call__'):
                return handler(request, *args, **kwargs)
        return HttpResponseBadRequest('Method Not Allowed', status=405)

Ich kann jetzt instanziiert beide Ansicht Klassen und Instanzen als View - Funktionen verwenden oder kann ich einfach meine URLconf meiner Klasse zeigen und haben die Metaklasse instantiate (und nennen) die Ansichtsklasse für mich. Dies funktioniert , indem das erste Argument zu überprüfen, __call__- wenn es ein ist HttpRequest, muss es eine tatsächliche HTTP - Anforderung sein , weil es unsinnig wäre , attept eine Ansichtsklasse mit einer instanziiert - HttpRequestInstanz.

class MyView(View):
    def __init__(self, arg=None):
        self.arg = arg
    def GET(request):
        return HttpResponse(self.arg or 'no args provided')

@login_required
class MyOtherView(View):
    def POST(request):
        pass

# And all the following work as expected.
urlpatterns = patterns(''
    url(r'^myview1$', 'myapp.views.MyView', name='myview1'),
    url(r'^myview2$', myapp.views.MyView, name='myview2'),
    url(r'^myview3$', myapp.views.MyView('foobar'), name='myview3'),
    url(r'^myotherview$', 'myapp.views.MyOtherView', name='otherview'),
)

(I posted einen Ausschnitt für diese bei http://djangosnippets.org/snippets/2041/ )

Beantwortet am 27/05/2010 um 14:02
quelle vom benutzer

stimmen
9

Wenn Sie einfach Daten von Modellen angezeigt wird , warum nicht die Verwendung Django Generic Views ? Sie sind entworfen , um Sie einfach zeigten Daten von einem Modell zu lassen , ohne Ihre eigene Sicht und Sachen über das Zuordnen von URL zu paramaters Ansichten zu schreiben, Abrufen von Daten, Kanten der Bearbeitung von Fällen, Rendering Ausgabe usw.

Beantwortet am 07/08/2008 um 11:44
quelle vom benutzer

stimmen
3

Sie können immer eine Klasse erstellen, überschreiben Sie die __call__Funktion und dann die URL - Datei der Klasse auf eine Instanz verweisen. Sie können einen Blick auf die nehmen FormWizard Klasse zu sehen , wie das gemacht wird.

Beantwortet am 26/08/2008 um 12:38
quelle vom benutzer

stimmen
2

Es sei denn, Sie etwas ein wenig komplexer tun möchten, mit Hilfe der generischen Ansichten sind der Weg zu gehen. Sie sind viel mächtiger als ihr Name schon sagt, und wenn Sie nur Modelldaten generische Ansichten anzeigen, sind die Arbeit machen.

Beantwortet am 11/08/2008 um 23:59
quelle vom benutzer

stimmen
2

Klingt für mich wie Sie zu kombinieren Dinge sind versucht, die nicht kombiniert werden sollten. Wenn Sie unterschiedliche Verarbeitung Ihrer Ansicht nach tun, je nachdem ob es ein Benutzer- oder Gruppenobjekt Sie versuchen dann, betrachten Sie zwei verschiedene Ansichtsfunktionen verwenden sollten.

Auf der anderen Seite kann es gemeinsame Idiome werden Sie aus Ihren object_detail Typ Ansichten extrahieren möchten würden ... vielleicht könnten Sie einen Dekorateur oder einfach nur Hilfsfunktionen?

-Dan

Beantwortet am 03/08/2008 um 18:40
quelle vom benutzer

stimmen
1

Sie können die Django Generic Views verwenden. Sie können ganz einfach die gewünschte Funktionalität gründlich Django generic Ansichten erreichen

Beantwortet am 08/10/2014 um 06:53
quelle vom benutzer

stimmen
1

Generic Views wird in der Regel der Weg zu gehen, aber letztlich sind Sie frei, URLs zu handhaben, wie Sie wollen. FormWizard tut Dinge in einer klassenbasierten Art und Weise, wie einige Anwendungen für RESTful APIs tun.

Im Grunde genommen mit einer URL Sie eine Reihe von Variablen und Ort gegeben sind eine aufrufbare zu bieten, was aufrufbar Sie bieten ist ganz Ihnen überlassen - der normale Weg ist, eine Funktion zur Verfügung zu stellen - aber letztlich stellt Django keine Beschränkungen auf, was Sie tun.

Ich stimme zu, dass noch ein paar Beispiele dafür, wie dies zu tun wäre gut, FormWizard ist wahrscheinlich der Ort, obwohl zu starten.

Beantwortet am 23/09/2008 um 20:05
quelle vom benutzer

stimmen
1

Wenn Sie gemeinsame Funktionalität zwischen den Seiten teilen möchten empfehle ich Ihnen bei benutzerdefinierten Tags suchen. Sie sind ganz einfach zu erstellen , und sind sehr mächtig.

Auch Vorlagen können von anderen Vorlagen erweitern . Auf diese Weise können Sie eine Basisvorlage haben das Layout der Seite einzurichten und diese zwischen anderen Vorlagen zu teilen , die in den Lücken zu füllen. Sie nisten können Vorlagen in beliebiger Tiefe; so dass Sie das Layout auf getrennte Gruppen von verwandten Seiten an einem Ort zu spezifizieren.

Beantwortet am 26/08/2008 um 12:30
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more