So schreiben Sie effiziente Ansichten, Modelle und Abfragen in Django

Ich mag Django. Es ist ein gut durchdachter und intuitiver Rahmen mit einem Namen, den ich laut aussprechen kann. Sie können es verwenden, um ein Projekt in Wochenendgröße schnell zu starten, und Sie können es auch verwenden, um vollständige Produktionsanwendungen in großem Maßstab auszuführen.

Ich habe beide Dinge getan und im Laufe der Jahre herausgefunden, wie einige der Funktionen von Django für maximale Effizienz genutzt werden können. Diese sind:

  • Klassenbasierte versus funktionsbasierte Ansichten
  • Django Modelle
  • Objekte mit Abfragen abrufen

Schauen wir uns an, wie Sie mit diesen Tools eine performante Django-Anwendung erstellen können, die angenehm zu erstellen und zu warten ist.

Klassenbasierte versus funktionsbasierte Ansichten

Denken Sie daran, dass Django alles Python unter der Haube ist. Bei Ansichten haben Sie zwei Möglichkeiten: Ansichtsfunktionen (manchmal als „funktionsbasierte Ansichten“ bezeichnet) oder klassenbasierte Ansichten.

Als ich ApplyByAPI vor Jahren zum ersten Mal erstellte, bestand es ursprünglich ausschließlich aus funktionsbasierten Ansichten. Diese bieten eine detaillierte Steuerung und eignen sich zur Implementierung komplexer Logik. Genau wie bei einer Python-Funktion haben Sie die vollständige Kontrolle (zum Guten oder Schlechten) über die Funktionsweise der Ansicht.

Mit einer großen Kontrolle geht jedoch eine große Verantwortung einher, und die Verwendung funktionsbasierter Ansichten kann etwas mühsam sein. Sie sind dafür verantwortlich, alle erforderlichen Methoden zu schreiben, damit die Ansicht funktioniert. Auf diese Weise können Sie Ihre Anwendung vollständig anpassen.

Im Fall von ApplyByAPI gab es nur wenige Stellen, an denen diese maßgeschneiderte Funktionalität wirklich notwendig war. Überall sonst erschwerten funktionsbasierte Ansichten mein Leben. Das Schreiben einer im Wesentlichen benutzerdefinierten Ansicht für normale Vorgänge wie das Anzeigen von Daten auf einer Listenseite wurde mühsam, sich wiederholend und fehleranfällig.

Bei funktionsbasierten Ansichten müssen Sie herausfinden, welche Django-Methoden implementiert werden müssen, um Anforderungen zu verarbeiten und Daten an Ansichten zu übergeben. Das Schreiben von Unit-Tests kann einige Arbeit erfordern. Kurz gesagt, die granulare Steuerung, die funktionsbasierte Ansichten bieten, erfordert auch eine gewisse granulare Langeweile, um ordnungsgemäß implementiert zu werden.

Am Ende habe ich ApplyByAPI zurückgehalten, während ich die meisten Ansichten in klassenbasierte Ansichten umgestaltet habe. Dies war keine kleine Menge an Arbeit und Umgestaltung, aber als es fertig war, hatte ich eine Menge winziger Ansichten, die einen großen Unterschied machten. Ich meine, schau dir nur diesen an:

class ApplicationsList(ListView): model = Application template_name = "applications.html" 

Es sind drei Zeilen. Meine Entwicklerergonomie und mein Leben wurden viel einfacher.

Sie können sich klassenbasierte Ansichten als Vorlagen vorstellen, die die meisten Funktionen abdecken, die eine App benötigt. Es gibt Ansichten zum Anzeigen von Listen von Dingen, zum Anzeigen einer Sache im Detail und zum Bearbeiten von Ansichten zum Ausführen von CRUD-Vorgängen (Erstellen, Lesen, Aktualisieren, Löschen).

Da die Implementierung einer dieser generischen Ansichten nur wenige Codezeilen erfordert, wurde meine Anwendungslogik dramatisch prägnant. Dies gab mir weniger wiederholten Code, weniger Stellen, an denen etwas schief gehen konnte, und eine übersichtlichere Anwendung im Allgemeinen.

Klassenbasierte Ansichten lassen sich schnell implementieren und verwenden. Die integrierten klassenbasierten generischen Ansichten erfordern möglicherweise weniger Arbeit zum Testen, da Sie keine Tests für die von Django bereitgestellte Basisansicht schreiben müssen. (Django führt dafür seine eigenen Tests durch. Ihre App muss nicht überprüft werden.)

Um eine generische Ansicht an Ihre Anforderungen anzupassen, können Sie eine generische Ansicht in Unterklassen unterteilen und Attribute oder Methoden überschreiben. In meinem Fall wurden meine Testdateien dramatisch kürzer, da ich nur Tests für die von mir hinzugefügten Anpassungen schreiben musste, ebenso wie die Zeit und die Ressourcen, die für deren Ausführung erforderlich waren.

Berücksichtigen Sie beim Abwägen der Wahl zwischen funktionsbasierten oder klassenbasierten Ansichten den Umfang der Anpassungen, die für die Ansicht erforderlich sind, und die zukünftige Arbeit, die zum Testen und Verwalten erforderlich ist.

Wenn die Logik allgemein ist, können Sie möglicherweise mit einer generischen klassenbasierten Ansicht den ersten Schritt machen. Wenn Sie eine ausreichende Granularität benötigen, um die Methoden einer Basisansicht neu zu schreiben, wird dies zu kompliziert. Ziehen Sie stattdessen eine funktionsbasierte Ansicht in Betracht.

Django Modelle

Modelle organisieren die zentralen Konzepte Ihrer Django-Anwendung, um sie flexibel, robust und einfach zu handhaben zu machen. Mit Bedacht eingesetzt, sind Modelle eine leistungsstarke Möglichkeit, Ihre Daten zu einer endgültigen Quelle der Wahrheit zusammenzufassen.

Wie Ansichten bietet Django einige integrierte Modelltypen für die einfache Implementierung der Basisauthentifizierung, einschließlich der Benutzer- und Berechtigungsmodelle. Für alles andere können Sie ein Modell erstellen, das Ihr Konzept widerspiegelt, indem Sie von einer übergeordneten Modellklasse erben.

class StaffMember(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) company = models.OneToOneField(Company, on_delete=models.CASCADE) def __str__(self): return self.company.name + " - " + self.user.email 

Wenn Sie ein benutzerdefiniertes Modell in Django erstellen, unterteilen Sie die Modellklasse von Django und nutzen die gesamte Leistung. Jedes Modell, das Sie erstellen, wird im Allgemeinen einer Datenbanktabelle zugeordnet. Jedes Attribut ist ein Datenbankfeld. Dies gibt Ihnen die Möglichkeit, Objekte zu erstellen, mit denen Menschen besser verstehen können.

Sie können ein Modell nützlich machen, indem Sie seine Felder definieren. Viele eingebaute Feldtypen werden bequem bereitgestellt. Diese helfen Django dabei, den Datentyp, das beim Rendern eines Formulars zu verwendende HTML-Widget und sogar die Anforderungen an die Formularvalidierung herauszufinden. Bei Bedarf können Sie benutzerdefinierte Modellfelder schreiben.

Datenbankbeziehungen können mithilfe eines ForeignKey-Felds (Many-to-One) oder eines ManyToManyField (geben Sie drei Vermutungen an) definiert werden. Wenn diese nicht ausreichen, gibt es auch ein OneToOneField.  

Zusammen ermöglichen diese die Definition von Beziehungen zwischen Ihren Modellen mit Komplexitätsstufen, die nur durch Ihre Vorstellungskraft begrenzt sind. (Abhängig von Ihrer Vorstellungskraft kann dies ein Vorteil sein oder auch nicht.)

Objekte mit Abfragen abrufen

Verwenden Sie den Manager Ihres Modells ( objectsstandardmäßig), um ein QuerySet zu erstellen. Dies ist eine Darstellung von Objekten in Ihrer Datenbank, die Sie mithilfe von Methoden verfeinern können, um bestimmte Teilmengen abzurufen. Alle verfügbaren Methoden befinden sich in der QuerySet-API und können für noch mehr Spaß miteinander verkettet werden.

Post.objects.filter( type="new" ).exclude( title__startswith="Blockchain" ) 

Einige Methoden geben neue QuerySets zurück, z. B. filter()oder exclude(). Wenn Sie diese verketten, können Sie leistungsstarke Abfragen erhalten, ohne die Leistung zu beeinträchtigen, da QuerySets erst aus der Datenbank abgerufen werden, wenn sie ausgewertet werden. Methoden , die eine QuerySet bewerten sind get(), count(), len(), list(), oder bool().

Durch Iterieren über ein QuerySet wird es ebenfalls ausgewertet. Vermeiden Sie dies daher nach Möglichkeit, um die Abfrageleistung zu verbessern. Wenn Sie beispielsweise nur wissen möchten, ob ein Objekt vorhanden ist, können Sie exists()vermeiden, dass Datenbankobjekte durchlaufen werden.

Verwenden get()Sie diese Option in Fällen, in denen Sie ein bestimmtes Objekt abrufen möchten. Diese Methode wird ausgelöst, MultipleObjectsReturnedwenn etwas Unerwartetes passiert, sowie die DoesNotExistAusnahme, wenn Sie eine Vermutung anstellen.

If you’d like to get an object that may not exist in the context of a user’s request, use the convenient get_object_or_404() or get_list_or_404() which raises Http404 instead of DoesNotExist. These helpful shortcuts are suited to just this purpose. To create an object that doesn’t exist, there’s also the convenient get_or_create().

Efficient essentials

You’ve now got a handle on these three essential tools for building your efficient Django application – congratulations!

There’s a lot more that Django can do for you, so stay tuned for future articles.

If you’re  going to build on GitHub, you may like to set up my django-security-check GitHub Action. In the meantime, you’re well on your way to building a beautiful software project.