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 anlegen

  • die dazugehörige VIEW in den event_manager/events/views.py erstellen

  • das 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 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 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.

../_images/category_overview.png

Mehr zum Thema Templates findet sich natürlich in der Django-Doku: https://docs.djangoproject.com/en/stable/topics/templates/