Views für die Kategorie
Bis konnten nur Administratoren die Daten sehen. Wir wollen sie jetzt der Öffentlichkeit zur Verfügung stellen und uns ein eigenes Frontend schreiben. Dazu benötigen wir einerseits die entsprechenden Views, die die Daten ausliefern und andererseits die URLs, die auf die Seiten führen. Zusätzlich müssen noch die HTML-Templates erstellt werden.
Für jede Aktion/Webseite, die wir entwickeln wollen, müssen wir also (mindestens) die folgenden drei Schritte ausführen:
einen URL in den urlpatterns von
event_manager/events/urls.py
anlegendie dazugehörige VIEW in den
event_manager/events/views.py
erstellendas entsprechende Template erstellen, in welches die Daten gerendert werden.
Wenn wir also eine Detail-Ansicht eines Events ermöglichen wollen, müssen wir eine URL dafür anlegen, unter der diese Detailseite erreichbar ist. Wir müssen eine View anlegen, die aufgerufen wird und die nötigen Daten aus der Datenbank zieht. Und wir müssen ein Template anlegen, in das die Daten gerendert werden.
Ein URL könnte zum Beispiel sein: http://127.0.0.1:8000/events
die uns alle Events auflistet.
Funktionsbasiert oder klassenbasiert
In Django gibt es zwei Arten von Möglichkeiten, Views zu entwicklen: die ältere aber sehr mächtige Art und Weise ist die sogenannte function-based
View, die View also als Funktion zu schreiben. Daneben gibt es für immer wiederkehrende Standardaufgaben noch die -sehr komfortable- klassenbasierte View.
Je nachdem, welches Problem gelöst werden soll, wählen wir zwischen den beiden.
Die Kategorien
Zuerst wollen wir eine Ausgabe aller bisher in der Datenbank hinterlegten Kategorien entwickeln, die sogenannte Kategorie-Übersicht. Die Views der Kategorie werden wir in funktionsbasierter Manier entwickeln. Später bei den Events werden wir uns die klassenbasierte Herangehensweise ansehen.
URLs
Legen wir die URLs für die Kategorie an. Erstmal wollen wir ja die Übersicht
der Kategorien darstellen.
Dazu tragen wir folgendes in die event_manager/events/urls.py
ein:
urlpatterns = [
path("hello_world", views.hello_world, name="hello_world"),
path("categories", views.categories, name="categories"),
]
Wir haben also eine neue Pfad-Angabe in unseren urlpatterns. Wenn ein User
jetzt http://127.0.0.1/events/categories
in seinen Browser eingibt, soll er
eine Übersicht aller Kategorien erhalten. Das erste Argument von path
ist
der URL-Pfad (innerhalb der App events), das zweite Argument ist die
Funktionsreferenz auf views.categories
, die von Django intern aufgerufen
wird und das dritte Argument ist ein Name, den wir später noch im Template
brauchen, um die Verlinkungen zu ermöglichen.
Die View gibt es noch nicht, deshalb kommt es aktuell auch noch zu einem Fehler.
Views
Erstellen wir jetzt die View für diese Route und tragen folgendes in event_manager/events/views.py
ein:
from django.shortcuts import render
from .models import Event, Category
def categories(request):
"""Funktion View, die alle Kategorien auflistet.
http://127.0.0.1:8000/events/categories
"""
categories_list = Category.objects.all()
return render(request,
"events/categories.html",
{"categories": categories_list})
Zuerst holen wir uns mit all()
alle Kategorien via dem objects-Manager
und weisen sie der Variable categories_list
zu.
Danach rufen wir die Funktion render()
auf, die drei Argumente erwartet:
das request-Objekt
den Pfad zum HTML-Template
der Context: das sind die Daten, die von der
Django Template Engine
in das Template gerendert werden sollen. Diese Daten werden in einem sogenanntenContext-Dictionary
übergeben. Der Zugriff auf die Daten später im Template erfolgt via dem Dict-Schlüssel. D.h. wenn wir im Template auf die Kategorie-Objekte zugreifen wollen, sprechen wir sie mit Keycategories
an.
Sehen wir uns jetzt an, wie das Template gerendert werden soll:
Templates
Damit unser Programm funtioniert, benötigen wir noch ein Template für die Ausgabe aller Kategorien. Die Django-Doku erklärt in einem Satz eigentlich ganz gut, was ein Template in diesem Sinne überhaupt ist:
A template is a text file. It can generate any text-based format (HTML, XML, CSV, etc.). A template contains variables, which get replaced with values when the template is evaluated, and tags, which control the logic of the template.
—Django Dokumentation, Templates
Es gibt in einem Template also Variablen, die Werte anzeigen können und Tags, die eine Logik mitbringen, um die Darstellung zu steuern.
Dazu legen wir im Verzeichnis event_manager/events
ein neues Verzeichnis
namens templates
an. In dieses Template-Verzeichnis kommt ein weiteres
Verzeichnis Namens events
.
Best Practice: Templates organisieren
Standardmäßig sucht der Django-Templateloader in jeder Anwendung nach einem
Vorlagenordner, falls APP_DIRS
in den settings.py
auf True
gesetzt wurde.
Damit es bei Templates mit gleichen Namen nicht zu Verwechslungen kommt, ist es notwendig, einen Namespace für die Templates anzulegen.
Für gewöhnlich wiederholt man den Namen der App, in unserem Fall also events.
Wenn ein Django-Projekt an Größe zunimmt, ist es oft bequemer, alle Templates
an einem Ort zu verwalten, als sie in vielen verteilten Apps zu suchen.
Dazu gibt man in den settings.py
in DIRS
weitere Templatepfade an, in denen der
Template-Loader nach dem Namen eines Templates sucht.
Die Template-Stuktur innerhalb einer App nach der Best Practice ist <APP-NAME>/templates/<APP-NAME>
events
├───fixtures
├───management
│ └───commands
├───migrations
├───templates
└───events
Wir legen jetzt die Datei event_manager/events/templates/events/categories.html
und füllen Sie mit diesem Inhalt.
Wir sehen hier jeweils ein Beispiel für einen Tag und für eine Variable:
<h1>Übersicht der Kategorien</h1>
<ul>
{% for category in categories %}
<li>
{{categoy.name}}
</li>
</a>
{% endfor %}
Der Tag ist der der for-Tag, der im Grunde einfach nur ein for-Loop ist,
wie man es aus Python kennt. Wir iterieren also über alle categories
und
legen in jeder Iteration auch noch gleich einen li-Tag an. Tags erkennt man
immer an der geschweiften Klammer und der Prozentzeichen. Viele Tags haben
einen öffnenden und schließenden Teil.
Die Variable ist die Ausgabe des Kategorie-Namens mit {{category.name}}
.
Variablen stehen in doppelten geschweiften Klammern und haben kein
Prozentzeichen.
Template Rendern
Wir haben gesehen, dass wir ein HTML-Gerüst erstellt hatten und dort dynamisch Daten hineingeschrieben haben.
Wem das gezeigte HTML fremd ist, der sollte mal kurz innehalten und sich die Definition einer ungeordneten Liste in HTML ansehen.
Wenn wir jetzt den runserver
starten, sollten wir unter http://127.0.0.1:8000/events/categories
die Kategorien in einer Liste sehen.
Mehr zum Thema Templates findet sich natürlich in der Django-Doku: https://docs.djangoproject.com/en/stable/topics/templates/