.. _create_views: .. index:: single: Views single: klassenbasierte Views single: funktionsbasierte Views single: Request-Objekt single: URLs single: Template Namespacing single: APP_DIRS single: DIRS siehe: Templates 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. .. admonition:: 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: .. code-block:: python 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: .. code-block:: python 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``. .. admonition:: 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 ``/templates/`` .. code-block:: bash 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: .. code-block:: html+django

Übersicht der Kategorien