Django-Highlights: Templating speichert Zeilen (Teil 2)
Veröffentlicht: 2022-03-10Einige schnörkellose Ansätze zum Erstellen von Websites erfordern, dass ein Entwickler jede HTML-Zeile von Hand schreibt. Auf der anderen Seite erstellen kommerzielle No-Code-Site-Builder den gesamten HTML-Code für den Benutzer automatisch, oft auf Kosten der Lesbarkeit des resultierenden Codes. Templating liegt ungefähr in der Mitte dieses Spektrums, aber näher an handgeschriebenem HTML als beispielsweise an der Generierung einer Seitenstruktur in einer Single-Page-Anwendung mit React oder einer ähnlichen Bibliothek. Dieser Sweet Spot auf dem Kontinuum bietet viele der Vorteile von HTML von Grund auf neu (semantischer/lesbarer Code, vollständige Kontrolle über die Seitenstruktur, schnelles Laden von Seiten) und fügt Trennung von Bedenken und Prägnanz hinzu, alles auf Kosten des Zeitaufwands für das Schreiben modifiziertes HTML von Hand. Dieser Artikel demonstriert die Verwendung von Django-Vorlagen zum Schreiben komplexer Seiten.
Das heutige Thema gilt über das Django-Framework hinaus. Flask (ein weiteres Web-Framework) und Pelican (ein statischer Site-Generator) sind nur zwei von vielen anderen Python-Projekten, die den gleichen Ansatz für die Erstellung von Vorlagen verwenden. Jinja2 ist die Templating-Engine, die alle drei Frameworks verwenden, obwohl Sie eine andere verwenden können, indem Sie die Projekteinstellungen ändern (genau genommen ist Jinja2 eine Obermenge von Django-Templating). Es ist eine freistehende Bibliothek, die Sie auch ohne Framework in Ihre eigenen Projekte integrieren können, sodass die Techniken aus diesem Artikel allgemein nützlich sind.
Vorherige Teile der Serie:
- Django-Highlights: Benutzermodelle und Authentifizierung (Teil 1)
- Django-Highlights: Modelle, Verwaltung und Nutzung der relationalen Datenbank (Teil 3)
- Django-Highlights: Umgang mit statischen Assets und Mediendateien (Teil 4)
Serverseitiges Rendern
Eine Vorlage ist nur eine HTML-Datei, in der das HTML mit zusätzlichen Symbolen erweitert wurde. Denken Sie daran, wofür HTML steht: H yper T ext M arkup L anguage. Jinja2, unsere Templating-Sprache, ergänzt die Sprache einfach um zusätzliche aussagekräftige Markup-Symbole. Diese zusätzlichen Strukturen werden interpretiert, wenn der Server die Vorlage rendert, um dem Benutzer eine einfache HTML-Seite bereitzustellen (das heißt, die zusätzlichen Symbole aus der Vorlagensprache schaffen es nicht in die endgültige Ausgabe).
Beim serverseitigen Rendern wird eine Webseite als Antwort auf eine Anfrage erstellt. Django verwendet serverseitiges Rendering, um dem Client HTML-Seiten bereitzustellen. Am Ende ihrer Ausführung kombiniert eine Ansichtsfunktion die HTTP-Anforderung, eine oder mehrere Vorlagen und optional Daten, auf die während der Ausführung der Funktion zugegriffen wird, um eine einzelne HTML-Seite zu erstellen, die sie als Antwort an den Client sendet. Daten gehen von der Datenbank durch die Ansicht und in die Vorlage, um ihren Weg zum Benutzer zu finden. Machen Sie sich keine Sorgen, wenn diese abstrakte Erklärung keinen Sinn ergibt, wir wenden uns für den Rest dieses Artikels einem konkreten Beispiel zu.
Einrichten
Für unser Beispiel nehmen wir eine ziemlich komplexe Webseite, starten Sie die Admin-Vorlage von Bootstrap, und schreiben den HTML-Code als Jinja2-Vorlage um. Beachten Sie, dass die MIT-lizenzierte Bibliothek ein anderes Templating-System (basierend auf JavaScript und Pug) verwendet, um die Seite zu generieren, die Sie sehen, aber ihr Ansatz unterscheidet sich wesentlich von Templating im Jinja2-Stil, sodass dieses Beispiel eher ein Reverse-Engineering als eine Übersetzung ist ihres hervorragenden Open-Source-Projekts. Um die Webseite zu sehen, die wir erstellen, können Sie sich die Live-Vorschau von Start Bootstrap ansehen.
Für diesen Artikel habe ich eine Musteranwendung vorbereitet. Um das Django-Projekt auf Ihrem eigenen Computer auszuführen, starten Sie Ihre virtuelle Python 3-Umgebung und führen Sie dann die folgenden Befehle aus:
pip install django git clone https://github.com/philipkiely/sm_dh_2_dashboard.git cd sm_dh_2_dashboard python manage.py migrate python manage.py createsuperuser python manage.py loaddata employee_fixture.json python manage.py runserver
Öffnen Sie dann Ihren Webbrowser und navigieren Sie zu https://127.0.0.1:8000
. Sie sollten dieselbe Seite wie die Vorschau sehen, die dem Bild unten entspricht.
Da sich dieses Tutorial auf das Frontend konzentriert, ist die zugrunde liegende Django-App sehr einfach. Dies mag wie eine Menge Konfiguration für die Darstellung einer einzelnen Webseite erscheinen, und um fair zu sein, ist es das auch. Allerdings könnte so viel Setup auch eine viel robustere Anwendung unterstützen.
Jetzt sind wir bereit, den Prozess der Umwandlung dieser 668-Zeilen-HTML-Datei in eine richtig gestaltete Django-Site durchzugehen.
Templating und Vererbung
Der erste Schritt beim Umgestalten von Hunderten von HTML-Zeilen in sauberen Code besteht darin, Elemente in ihre eigenen Vorlagen aufzuteilen, die Django während des Rendering-Schritts zu einer einzigen Webseite zusammensetzt.
Schauen Sie in Seiten/Vorlagen nach. Sie sollten fünf Dateien sehen:
- base.html , die Basisvorlage, die jede Webseite erweitert. Es enthält den
<head>
mit dem Titel, CSS-Importe usw. - navbar.html , das HTML für die obere Navigationsleiste, eine Komponente, die bei Bedarf eingefügt werden muss.
- footer.html , der Code für den Seitenfuß, eine weitere Komponente, die bei Bedarf eingefügt werden muss.
- sidebar.html , das HTMl für die Seitenleiste, eine dritte Komponente, die bei Bedarf eingefügt werden muss.
- index.html , der für die Hauptseite eindeutige Code. Diese Vorlage erweitert die Basisvorlage und enthält die drei Komponenten.
Django stellt diese fünf Dateien wie Voltron zusammen, um die Indexseite zu rendern. Die Schlüsselwörter, die dies zulassen, sind {% block %}
, {% include %}
und {% extend %}
. In base.html :
{% block content %} {% endblock %}
Diese beiden Zeilen lassen Platz für andere Templates, die base.html erweitern, um ihr eigenes HTML einzufügen. Beachten Sie, dass content
ein variabler Name ist. Sie können mehrere Blöcke mit unterschiedlichen Namen in einer Vorlage haben, was untergeordneten Vorlagen Flexibilität verleiht. Wir sehen, wie man dies in index.html erweitert:
{% extends "base.html" %} {% block content %} <!-- HTML Goes Here --> {% endblock %}
Die Verwendung des Schlüsselworts extends
mit dem Namen der Basisvorlage gibt der Indexseite ihre Struktur und erspart uns das Kopieren in die Überschrift (beachten Sie, dass der Dateiname ein relativer Pfad in doppelter Anführungszeichen-Zeichenfolge ist). Die Indexseite enthält alle drei Komponenten, die den meisten Seiten der Website gemeinsam sind. Wir bringen diese Komponenten mit include
-Tags wie folgt ein:
{% extends "base.html" %} {% block content %} {% include "navbar.html" %} {% include "sidebar.html" %} <!--Index-Specific HTML--> {% include "footer.html" %} <!--More Index-Specific HTML--> {% endblock %}
Insgesamt bietet diese Struktur drei wesentliche Vorteile gegenüber dem einzelnen Schreiben von Seiten:
- DRY (Don't Repeat Yourself) Code
Indem wir gemeinsamen Code in bestimmte Dateien ausgliedern, können wir den Code nur an einer Stelle ändern und diese Änderungen auf allen Seiten widerspiegeln. - Erhöhte Lesbarkeit
Anstatt durch eine riesige Datei zu scrollen, können Sie die spezifische Komponente, an der Sie interessiert sind, isolieren. - Trennung von Bedenken
Der Code für beispielsweise die Seitenleiste muss jetzt an einer Stelle sein, es dürfen keine Rogue-script
-Tags am Ende des Codes schweben oder sich anderweitig zwischen Komponenten vermischen, die eigentlich getrennt sein sollten. Das Ausklammern einzelner Teile erzwingt diese gute Kodierungspraxis.
Wir könnten zwar noch mehr Codezeilen einsparen, indem wir die spezifischen Komponenten in die base.html- Vorlage einfügen, aber die Trennung bietet zwei Vorteile. Das erste ist, dass wir sie genau dort einbetten können, wo sie in einem einzelnen Block hingehören (dies ist nur für die footer.html relevant, die in das Haupt- div
des content
eingefügt wird). Der andere Vorteil ist, dass wir, wenn wir eine Seite erstellen würden, sagen wir eine 404-Fehlerseite, und wir die Seitenleiste oder Fußzeile nicht wollten, diese weglassen könnten.
Diese Fähigkeiten sind für das Templating selbstverständlich. Jetzt wenden wir uns leistungsstarken Tags zu, die wir in unserer index.html verwenden können, um dynamische Funktionen bereitzustellen und Hunderte von Codezeilen einzusparen.
Zwei grundlegende Tags
Dies ist bei weitem keine erschöpfende Liste verfügbarer Tags. Die Django-Dokumentation zum Templating bietet eine solche Aufzählung. Im Moment konzentrieren wir uns auf die Anwendungsfälle für zwei der häufigsten Elemente der Templating-Sprache. In meiner eigenen Arbeit verwende ich grundsätzlich nur die for
und if
-Tags regelmäßig, obwohl das Dutzend oder mehr andere bereitgestellte Tags ihre eigenen Anwendungsfälle haben, die Sie in der Vorlagenreferenz überprüfen sollten.
Bevor wir zu den Tags kommen, möchte ich eine Anmerkung zur Syntax machen. Das Tag {% foo %}
bedeutet, dass „foo“ eine Funktion oder eine andere Fähigkeit des Templating-Systems selbst ist, während das Tag {{ bar }}
bedeutet, dass „bar“ eine Variable ist, die an das spezifische Template übergeben wird.
Für Schleifen
In der verbleibenden index.html ist der mit mehreren hundert Zeilen größte Codeabschnitt die Tabelle. Anstelle dieser hartcodierten Tabelle können wir die Tabelle dynamisch aus der Datenbank generieren. Rufen Sie python manage.py loaddata employee_fixture.json
aus dem Einrichtungsschritt auf. Dieser Befehl verwendete eine JSON-Datei namens Django Fixture, um alle 57 Mitarbeiterdatensätze in die Datenbank der Anwendung zu laden. Wir verwenden die Ansicht in views.py , um diese Daten an die Vorlage zu übergeben:
from django.shortcuts import render from .models import Employee def index(request): return render(request, "index.html", {"employees": Employee.objects.all()})
Das dritte zu render
Positionsargument ist ein Wörterbuch mit Daten, das der Vorlage zur Verfügung gestellt wird. Wir verwenden diese Daten und das for
-Tag, um die Tabelle zu erstellen. Sogar in der ursprünglichen Vorlage, aus der ich diese Webseite angepasst habe, war die Tabelle der Mitarbeiter fest codiert. Unser neuer Ansatz schneidet Hunderte von Zeilen sich wiederholender festcodierter Tabellenzeilen ab. index.html enthält jetzt:
{% for employee in employees %} <trv <td>{{ employee.name }}</td> <td>{{ employee.position }}</td> <td>{{ employee.office }}</td> <td>{{ employee.age }}</td> vtd>{{ employee.start_date }}</td> <td>${{ employee.salary }}</td> </tr> {% endfor %}
Der größere Vorteil besteht darin, dass die Aktualisierung der Tabelle dadurch erheblich vereinfacht wird. Anstatt einen Entwickler den HTML-Code manuell bearbeiten zu lassen, um eine Gehaltserhöhung oder Neueinstellung widerzuspiegeln, und diese Änderung dann in die Produktion zu übertragen, kann jeder Administrator das Admin-Panel verwenden, um Echtzeit-Updates vorzunehmen (https://127.0.0.1/admin, use die Anmeldeinformationen, die Sie mit python manage.py createsuperuser
, erstellt Superuser für den Zugriff). Dies ist ein Vorteil der Verwendung von Django mit dieser Rendering-Engine, anstatt sie allein in einem statischen Site-Generator oder einem anderen Templating-Ansatz zu verwenden.
Ansonsten
Das if
-Tag ist ein unglaublich leistungsfähiges Tag, mit dem Sie Ausdrücke innerhalb der Vorlage auswerten und den HTML-Code entsprechend anpassen können. Zeilen wie {% if 1 == 2 %}
sind vollkommen gültig, wenn auch ein wenig nutzlos, da sie jedes Mal zu demselben Ergebnis führen. Wo das if
-Tag leuchtet, ist bei der Interaktion mit Daten, die von der Ansicht an die Vorlage übergeben werden. Betrachten Sie das folgende Beispiel aus sidebar.html :
<div class="sb-sidenav-footer"> <div class="small"> Logged in as: </div> {% if user.is_authenticated %} {{ user.username }} {% else %} Start Bootstrap {% endif %} </div>
Beachten Sie, dass standardmäßig das gesamte Benutzerobjekt an die Vorlage übergeben wird, ohne dass wir etwas in der Ansicht angeben, um dies zu erreichen. Dies ermöglicht uns den Zugriff auf den Authentifizierungsstatus des Benutzers (oder dessen Fehlen), den Benutzernamen und andere Funktionen, einschließlich der folgenden Fremdschlüsselbeziehungen, um auf Daten zuzugreifen, die in einem Benutzerprofil oder einem anderen verbundenen Modell gespeichert sind, alles aus der HTML-Datei.
Sie könnten besorgt sein, dass diese Zugriffsebene Sicherheitsrisiken darstellen könnte. Denken Sie jedoch daran, dass diese Vorlagen für ein serverseitiges Rendering-Framework bestimmt sind. Nach dem Aufbau der Seite haben sich die Tags selbst verbraucht und werden durch reines HTML ersetzt. Wenn also eine if
-Anweisung unter bestimmten Bedingungen Daten in eine Seite einfügt, die Daten jedoch in einem bestimmten Fall nicht verwendet werden, werden diese Daten überhaupt nicht an den Client gesendet, da die if
-Anweisung serverseitig ausgewertet wird. Dies bedeutet, dass eine richtig erstellte Vorlage eine sehr sichere Methode zum Hinzufügen sensibler Daten zu Seiten ist, ohne dass diese Daten den Server verlassen, sofern dies nicht erforderlich ist. Die Verwendung von Django-Templating beseitigt jedoch nicht die Notwendigkeit, vertrauliche Informationen auf sichere und verschlüsselte Weise zu übermitteln. Es bedeutet lediglich, dass Sicherheitsprüfungen wie user.is_authenticated
sicher im HTML-Code durchgeführt werden können, während dieser serverseitig verarbeitet wird.
Diese Funktion hat eine Reihe anderer Anwendungsfälle. Beispielsweise möchten Sie auf einer allgemeinen Produkthomepage möglicherweise die Schaltflächen „Registrieren“ und „Anmelden“ ausblenden und sie durch eine Schaltfläche „Abmelden“ für angemeldete Benutzer ersetzen. Eine weitere häufige Verwendung ist das Ein- und Ausblenden von Erfolgs- oder Fehlermeldungen für Vorgänge wie das Absenden von Formularen. Beachten Sie, dass Sie im Allgemeinen nicht die gesamte Seite ausblenden würden, wenn der Benutzer nicht angemeldet ist. Eine bessere Möglichkeit, die gesamte Webseite basierend auf dem Authentifizierungsstatus des Benutzers zu ändern, besteht darin, sie in der entsprechenden Funktion in views.py zu behandeln.
Filtern
Ein Teil der Aufgabe der Ansicht besteht darin, Daten für die Seite angemessen zu formatieren. Um dies zu erreichen, haben wir eine leistungsstarke Erweiterung für Tags: Filter. In Django sind viele Filter verfügbar, um Aktionen wie das Ausrichten von Text, das Formatieren von Datumsangaben und das Hinzufügen von Zahlen durchzuführen. Grundsätzlich können Sie sich einen Filter als eine Funktion vorstellen, die auf die Variable in einem Tag angewendet wird. Beispielsweise möchten wir, dass unsere Gehaltszahlen „1.200.000 $“ statt „1200.000“ lauten. Wir verwenden einen Filter, um die Arbeit in index.html zu erledigen:
<td>${{ employee.salary|intcomma }}</td>
Das Pipe-Zeichen |
ist der Filter, der den Befehl intcomma
auf die Variable employee.salary
anwendet. Das „$“-Zeichen stammt nicht aus der Vorlage, für ein solches Element, das jedes Mal auftaucht, ist es einfacher, es einfach außerhalb des Tags zu platzieren.
Beachten Sie, dass intcomma
erfordert, dass wir {% load humanize %}
oben in unserer index.html und 'django.contrib.humanize',
in unseren INSTALLED_APPS
in settings.py einfügen. Dies wird für Sie in der mitgelieferten Musteranwendung erledigt.
Fazit
Das serverseitige Rendering mit der Jinja2-Engine bietet wichtige Tools zum Erstellen von sauberem, anpassbarem und reaktionsschnellem Front-End-Code. Das Trennen von Seiten in Dateien ermöglicht DRY-Komponenten mit flexibler Zusammensetzung. Tags bieten grundlegende Fähigkeiten zum Anzeigen von Daten, die von Ansichtsfunktionen aus der Datenbank übergeben werden. Richtig gemacht, kann dieser Ansatz die Geschwindigkeit, die SEO-Fähigkeiten, die Sicherheit und die Benutzerfreundlichkeit der Website erhöhen und ist ein Kernaspekt der Programmierung in Django und ähnlichen Frameworks.
Sehen Sie sich die Beispielanwendung an, falls Sie dies noch nicht getan haben, und versuchen Sie, mithilfe der vollständigen Liste Ihre eigenen Tags und Filter hinzuzufügen.
Django Highlights ist eine Serie, in der wichtige Konzepte der Webentwicklung in Django vorgestellt werden. Jeder Artikel ist als eigenständiger Leitfaden zu einer Facette der Django-Entwicklung geschrieben, der Front-End-Entwicklern und -Designern helfen soll, ein tieferes Verständnis der „anderen Hälfte“ der Codebasis zu erlangen. Diese Artikel sind hauptsächlich darauf ausgelegt, Ihnen zu helfen, Theorie und Konventionen zu verstehen, enthalten jedoch einige Codebeispiele, die in Django 3.0 geschrieben wurden.
Vorherige Teile der Serie:
- Django-Highlights: Benutzermodelle und Authentifizierung (Teil 1)
- Django-Highlights: Modelle, Verwaltung und Nutzung der relationalen Datenbank (Teil 3)
- Django-Highlights: Umgang mit statischen Assets und Mediendateien (Teil 4)