Frage

Django view verweist auf eine Funktion, was ein Problem sein kann, wenn Sie nur einen Teil der Funktionalität ändern möchten.Ja, ich könnte Millionen Schlüsselwortargumente und noch mehr if-Anweisungen in der Funktion haben, aber ich dachte eher an einen objektorientierten Ansatz.

Ich habe zum Beispiel eine Seite, die einen Benutzer anzeigt.Diese Seite ist der Seite, die eine Gruppe anzeigt, sehr ähnlich, aber es ist immer noch nicht so ähnlich, einfach ein anderes Datenmodell zu verwenden.Die Gruppe hat auch Mitglieder usw.

Eine Möglichkeit wäre, Ansichten auf Klassenmethoden zu verweisen und diese Klasse dann zu erweitern.Hat jemand diesen Ansatz ausprobiert oder hat er eine andere Idee?

War es hilfreich?

Lösung

Ich habe meine eigenen generischen Ansichtsklassen erstellt und verwendet, um sie zu definieren __call__ Daher ist eine Instanz der Klasse aufrufbar.Ich mag es wirklich;Während die generischen Ansichten von Django eine gewisse Anpassung über Schlüsselwortargumente ermöglichen, können generische OO-Ansichten (wenn ihr Verhalten in eine Reihe separater Methoden aufgeteilt ist) über Unterklassen eine viel feinkörnigere Anpassung ermöglichen, wodurch ich mich viel weniger wiederholen muss.(Ich habe es satt, die gleiche Logik zum Erstellen/Aktualisieren von Ansichten jedes Mal neu zu schreiben, wenn ich etwas optimieren muss, das die generischen Ansichten von Django nicht ganz zulassen.)

Ich habe Code unter gepostet djangosnippets.org.

Der einzige wirkliche Nachteil, den ich sehe, ist die Verbreitung interner Methodenaufrufe, die sich etwas auf die Leistung auswirken können.Ich denke nicht, dass dies ein großes Problem darstellt.Es kommt selten vor, dass die Ausführung von Python-Code zu einem Leistungsengpass in einer Web-App führt.

AKTUALISIEREN:Djangos eigenes generische Ansichten sind jetzt klassenbasiert.

AKTUALISIEREN:FWIW, ich habe meine Meinung zu klassenbasierten Ansichten geändert, seit diese Antwort geschrieben wurde.Nachdem ich sie in einigen Projekten ausgiebig verwendet habe, habe ich das Gefühl, dass sie dazu neigen, zu Code zu führen, der zwar zufriedenstellend zu schreiben ist, aber später sehr schwer zu lesen und zu warten ist, weil die Funktionalität auf so viele verschiedene Orte verteilt ist und Unterklassen so abhängig sind zu jedem Implementierungsdetail der Superklassen und Mixins.Das spüre ich jetzt TemplateResponse und Ansichtsdekoratoren sind eine bessere Antwort zum Zerlegen von Ansichtscode.

Andere Tipps

Ich musste klassenbasierte Ansichten verwenden, wollte aber in der Lage sein, den vollständigen Namen der Klasse in meiner URLconf zu verwenden, ohne die Ansichtsklasse vor der Verwendung immer instanziieren zu müssen.Was mir geholfen hat, war eine überraschend einfache Metaklasse:

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 sowohl Ansichtsklassen instanziieren als auch die Instanzen als Ansichtsfunktionen verwenden, ODER ich kann einfach meine URLconf auf meine Klasse verweisen und die Metaklasse die Ansichtsklasse für mich instanziieren (und aufrufen) lassen.Dies funktioniert, indem das erste Argument überprüft wird __call__ – wenn es ein ist HttpRequest, es muss sich um eine tatsächliche HTTP-Anfrage handeln, da es Unsinn wäre, zu versuchen, eine Ansichtsklasse mit einer zu instanziieren HttpRequest Beispiel.

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

(Ich habe einen Ausschnitt dazu gepostet unter http://djangosnippets.org/snippets/2041/)

Wenn Sie lediglich Daten von Modellen anzeigen, verwenden Sie doch die Generische Django-Ansichten?Sie sind so konzipiert, dass Sie auf einfache Weise Daten aus einem Modell anzeigen können, ohne Ihre eigene Ansicht schreiben zu müssen und sich mit der Zuordnung von URL-Parametern zu Ansichten, dem Abrufen von Daten, der Handhabung von Grenzfällen, dem Rendern der Ausgabe usw. befassen zu müssen.

Sie können jederzeit eine Klasse erstellen und diese überschreiben __call__ Funktion und verweisen Sie dann die URL-Datei auf eine Instanz der Klasse.Sie können einen Blick darauf werfen Formzauberer Klasse, um zu sehen, wie das gemacht wird.

Für mich hört sich das so an, als würden Sie versuchen, Dinge zu kombinieren, die nicht kombiniert werden sollten.Wenn Sie in Ihrer Ansicht unterschiedliche Verarbeitungen durchführen müssen, je nachdem, ob es sich um ein Benutzer- oder Gruppenobjekt handelt, das Sie betrachten möchten, sollten Sie zwei verschiedene Ansichtsfunktionen verwenden.

Andererseits kann es gängige Redewendungen geben, die Sie aus Ihren Ansichten vom Typ „object_detail“ extrahieren möchten ...Vielleicht könnten Sie einen Dekorateur oder nur Hilfsfunktionen verwenden?

-Dan

Sofern Sie nicht etwas Komplexeres tun möchten, ist die Verwendung der generischen Ansichten die richtige Wahl.Sie sind weitaus leistungsfähiger, als ihr Name vermuten lässt, und wenn Sie nur Modelldaten anzeigen, reichen generische Ansichten aus.

Generische Ansichten sind in der Regel der richtige Weg, aber letztlich steht es Ihnen frei, mit URLs so umzugehen, wie Sie möchten.FormWizard erledigt Dinge auf klassenbasierte Weise, ebenso wie einige Apps für RESTful-APIs.

Grundsätzlich erhalten Sie mit einer URL eine Reihe von Variablen und den Ort, an dem Sie ein aufrufbares Element bereitstellen können. Welches aufrufbare Element Sie bereitstellen, liegt ganz bei Ihnen – die Standardmethode besteht darin, eine Funktion bereitzustellen – aber letztendlich legt Django keine Einschränkungen auf, was Sie tun.

Ich stimme zu, dass ein paar weitere Beispiele dafür gut wären, aber FormWizard ist wahrscheinlich der Ausgangspunkt.

Wenn Sie gemeinsame Funktionen zwischen Seiten teilen möchten, empfehle ich Ihnen, einen Blick auf benutzerdefinierte Tags zu werfen.Sie sind ruhig einfach zu erstellen, und sind sehr mächtig.

Auch, Vorlagen können von anderen Vorlagen ausgehen.Auf diese Weise können Sie über eine Basisvorlage verfügen, um das Layout der Seite einzurichten und diese mit anderen Vorlagen zu teilen, die die Lücken füllen.Sie können Vorlagen beliebig tief verschachteln;So können Sie das Layout für separate Gruppen zusammengehöriger Seiten an einem Ort festlegen.

Sie können die generischen Django-Ansichten verwenden.Mit generischen Django-Ansichten können Sie die gewünschte Funktionalität ganz einfach erreichen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top