Views für die Kategorie

Bisher konnten nur Administratoren die Daten im Admin-Bereich einsehen. Nun stellen wir diese Inhalte über ein eigenes Frontend öffentlich bereit.

Dafür benötigen wir drei zentrale Komponenten:

  • Views, die Daten aus der Datenbank laden

  • URLs, über die diese Views erreichbar sind

  • Templates, die die Daten darstellen

Für jede Seite oder Funktionalität im Frontend sind daher mindestens folgende Schritte notwendig:

  • eine URL in event_manager/events/urls.py definieren

  • die passende View in event_manager/events/views.py implementieren

  • ein Template erstellen, in dem die Daten gerendert werden

Möchten wir beispielsweise eine Detailansicht für ein Event bereitstellen, benötigen wir:

  • eine URL, unter der die Seite erreichbar ist

  • eine View, die das entsprechende Event aus der Datenbank lädt

  • ein Template, das die Daten darstellt

Ein einfaches Beispiel für eine URL ist:

http://127.0.0.1:8000/events

Diese könnte verwendet werden, um eine Liste aller Events anzuzeigen.

Funktionsbasiert oder klassenbasiert

In Django gibt es zwei grundlegende Arten, Views zu implementieren: funktionsbasierte Views (Function-Based Views, FBV) und klassenbasierte Views (Class-Based Views, CBV).

Funktionsbasierte Views sind einfach aufgebaut und bieten maximale Kontrolle über den Ablauf. Klassenbasierte Views hingegen stellen für häufige Anwendungsfälle (z. B. Listen- oder Detailansichten) bereits vorgefertigte Strukturen bereit und reduzieren so Boilerplate-Code.

Welche Variante sinnvoll ist, hängt vom konkreten Anwendungsfall ab.

Die Kategorien

Zunächst entwickeln wir eine Übersicht aller in der Datenbank gespeicherten Kategorien, also eine Kategorie-Listenansicht.

Die Views für die Kategorien implementieren wir dabei funktionsbasiert. Für die Events werden wir später die klassenbasierte Herangehensweise kennenlernen.

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.

    /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 sogenannten Context-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 Key categories 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 Verzeichnis names templates, falls APP_DIRS in den den Template-Settings in der 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. Wir sehen in diesem Buch davon ab.

Die Template-Stuktur innerhalb einer App nach der Best Practice ist <APP-NAME>/templates/<APP-NAME>

events
    ├───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>
{% 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.

../_images/category_overview.png

Mehr zum Thema Templates findet sich natürlich in der Django-Doku:

https://docs.djangoproject.com/en/stable/topics/templates/