python - Klassenansichten in Django

Translate

DjangoAnsicht zeigt auf eine Funktion, die ein Problem sein kann, wenn Sie nur ein wenig Funktionalität ändern möchten. Ja, ich könnte Millionen von Keyword-Argumenten und noch mehr if-Anweisungen in der Funktion haben, aber ich dachte eher an einen objektorientierten Ansatz.

Zum Beispiel habe ich eine Seite, auf der ein Benutzer angezeigt wird. Diese Seite ist der Seite, auf der eine Gruppe angezeigt wird, sehr ähnlich, aber es ist immer noch nicht so ähnlich, nur ein anderes Datenmodell zu verwenden. Gruppe hat auch Mitglieder etc ...

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?

This question and all comments follow the "Attribution Required."

Alle Antworten

Translate

Ich habe meine eigenen generischen Ansichtsklassen erstellt und verwendet und definiert__call__Eine Instanz der Klasse kann also aufgerufen werden. Ich mag es wirklich; Während die generischen Ansichten von Django eine gewisse Anpassung durch Schlüsselwortargumente ermöglichen, können generische OO-Ansichten (wenn ihr Verhalten in mehrere separate Methoden aufgeteilt ist) eine viel feinere Anpassung über Unterklassen aufweisen, wodurch ich mich viel weniger wiederholen kann. (Ich habe es satt, die gleiche Logik zum Erstellen / Aktualisieren von Ansichten immer dann neu zu schreiben, wenn ich etwas optimieren muss, das Djangos generische Ansichten nicht ganz zulassen).

Ich habe einen Code bei gepostetdjangosnippets.org.

Der einzige wirkliche Nachteil, den ich sehe, ist die Verbreitung interner Methodenaufrufe, die die Leistung etwas beeinträchtigen können. Ich denke nicht, dass dies ein großes Problem ist. Es ist selten, dass die Ausführung von Python-Code Ihr Leistungsengpass in einer Web-App ist.

AKTUALISIEREN: Djangos eigenegenerische Ansichtensind 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 zu Code führen, der zufriedenstellend trocken zu schreiben ist, aber später sehr schwer zu lesen und zu warten ist, da die Funktionalität auf so viele verschiedene Orte verteilt ist und Unterklassen so abhängig sind zu jedem Implementierungsdetail der Superklassen und Mixins. Ich fühle das jetztTemplateResponseund Ansichtsdekorateure sind eine bessere Antwort für die Zerlegung von Ansichtscode.

Quelle
Translate

Ich musste klassenbasierte Ansichten verwenden, wollte aber den vollständigen Namen der Klasse in meiner URLconf verwenden können, 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). Dies funktioniert, indem das erste Argument auf überprüft wird__call__- wenn es ein istHttpRequestmuss es sich um eine tatsächliche HTTP-Anforderung handeln, da es unsinnig wäre, zu versuchen, eine Ansichtsklasse mit einem zu instanziierenHttpRequestBeispiel.

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 dafür bei gepostethttp://djangosnippets.org/snippets/2041/)

Quelle
Translate

Wenn Sie nur Daten von Modellen anzeigen, verwenden Sie dieDjango Generische Ansichten? Mit ihnen können Sie auf einfache Weise Daten aus einem Modell anzeigen, ohne Ihre eigene Ansicht und Informationen zum Zuordnen von URL-Parametern zu Ansichten, Abrufen von Daten, Behandeln von Randfällen, Rendern von Ausgaben usw. schreiben zu müssen.

Quelle
Translate

Sie können jederzeit eine Klasse erstellen, die überschreiben__call__Funktion und zeigen Sie dann die URL-Datei auf eine Instanz der Klasse. Sie können einen Blick auf dieFormzaubererKlasse, um zu sehen, wie das gemacht wird.

Quelle
Lynn Lee
Translate

Klingt für mich so, als würden Sie versuchen, Dinge zu kombinieren, die nicht kombiniert werden sollten. Wenn Sie in Ihrer Ansicht unterschiedliche Verarbeitungsschritte ausfü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.

Auf der anderen Seite kann es allgemeine Redewendungen geben, die Sie aus Ihren Ansichten vom Typ object_detail extrahieren möchten. Vielleicht könnten Sie einen Dekorator oder nur Hilfsfunktionen verwenden?

-Dan

Quelle
Translate

Wenn Sie nicht etwas Komplexes tun möchten, ist die Verwendung der generischen Ansichten der richtige Weg. Sie sind weitaus leistungsfähiger als der Name vermuten lässt. Wenn Sie nur Modelldaten anzeigen, sind generische Ansichten ausreichend.

Quelle
Translate

Generische Ansichten sind normalerweise der richtige Weg, aber letztendlich können Sie URLs beliebig verarbeiten. FormWizard erledigt die Dinge auf Klassenbasis, ebenso wie einige Apps für RESTful-APIs.

Grundsätzlich erhalten Sie mit einer URL eine Reihe von Variablen und einen Ort, an dem Sie einen Callable bereitstellen können. Was Sie aufrufen können, liegt ganz bei Ihnen - die Standardmethode besteht darin, eine Funktion bereitzustellen -, aber letztendlich legt Django keine Einschränkungen für Ihre Arbeit fest.

Ich bin damit einverstanden, dass ein paar weitere Beispiele dafür gut wären. FormWizard ist jedoch wahrscheinlich der Ausgangspunkt.

Quelle
Translate

Wenn Sie gemeinsame Funktionen zwischen Seiten nutzen möchten, empfehlen wir Ihnen, sich benutzerdefinierte Tags anzusehen. Sie sind ziemlicheinfach zu erstellenund sind sehr mächtig.

Ebenfalls,Vorlagen können von anderen Vorlagen erweitert werden. Auf diese Weise können Sie über eine Basisvorlage verfügen, um das Layout der Seite einzurichten und diese für andere Vorlagen freizugeben, die die Lücken ausfüllen. Sie können Vorlagen in beliebiger Tiefe verschachteln. So können Sie das Layout auf separaten Gruppen verwandter Seiten an einer Stelle festlegen.

Quelle
Translate

Sie können die generischen Django-Ansichten verwenden. Sie können die gewünschte Funktionalität leicht durch generische Django-Ansichten erreichen

Quelle