", views.category_detail, name="category_detail"),
]
Das heisst, wenn wir ``http://127.0.0.1:8000/events/category/3`` via Browser aufrufen, sollte uns die Detailansicht einer Kategorie ausgegeben werden.
Die View für die Detailseite der Kategorie
---------------------------------------------
Die View ``category_detail`` existiert in den ``views.py`` noch nicht, deshalb legen wir sie an. Lade das entsprechende Objekt aus der Datenbank, und werfen eine 404 Not Found Exception, falls das Objekt nicht gefunden wird.
Die Http404 Exception muss importiert werden:
.. code-block:: python
from django.http import Http404
def category_detail(request, id: int):
"""
die Detailseite einer Kategorie
http://127.0.0.1:8000/events/category/3
"""
try:
category = Company.objects.get(pk=id)
except Company.DoesNotExist:
raise Http404("Diese Kategorie existiert nicht")
return render(request, 'events/category_detail.html', {
'category': category
})
.. admonition:: 404 Fehler
Wenn eine URL nicht angezeigt werden kann, weil zum Beispiel das gesuchte Objekt nicht in der Datenbank vorhanden ist, lösen wir einen ``Http404-Fehler`` aus. Dem User wird daraufhin eine 404-Fehlerseite angezeigt (Not found), die wir später noch als Template anlegen werden.
Falls wir in den ``event_manager/settings.py`` ``DEBUG=True`` gesetzt haben, bekommen wir eine ausführliche Fehlerseite angezeigt, die uns detailliert aufzeigt, wo das Problem liegt. Im Live-Modus sollte zwingend ``DEBUG=False`` sein. Dann könnten wir unsere ``eigene 404-Fehlerseite`` anzeigen.
Wir rendern das Kategorieobjekt ``category`` in das Template ``event_manager/events/templates/events/category_detail.html``.
Das Template für die Detailseite der Kategorie
-----------------------------------------------
Legen wir eine neue Datei ``event_manager/events/templates/events/category_detail.html`` im Template-Ordner der App an und kopieren folgenden Inhalt hinein:
.. code-block:: html+django
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
Kategorie {{category.name}}
{%endblock%}
{% block head %}
Kategorie {{category.name}}
{%endblock%}
{% block content %}
{{category.description}}
created at: {{category.created_at}}
{%endblock%}
Wenn wir jetzt eine Detailseite aufrufen, sollte das klappen. Dazu starten wir den Runsever mit ``python manage.py runserver`` und navigieren auf die URL ``http://127.0.0.1:8000/events/category/3``.
Da sollte funktionieren. Wir wollen jetzt noch eine weitere Änderung vornehmen, bevor wir uns an die Verlinkung machen. Eine URL wie ``http://127.0.0.1:8000/events/category/3`` ist zwar möglich, aber nicht schön.
Da wir beim Entwickeln der Models für Events und Kategorien ja schon einen Slug eingebaut haben, wollen wir den jetzt auch gleich nutzen. Wir können dann die URLs im Format ``http://127.0.0.1:8000/events/category/sport`` aufrufen.
Dazu ändern wir die ``urlpatterns`` in den ``event_manager/events/urls.py`` ab:
.. code-block:: python
urlpatterns = [
path("hello_world", views.hello_world, name="hello_world"),
path("categories", views.list_categories, name="categories"),
# diese Zeile ändern:
path("category/", views.category_detail, name="category_detail"),
]
und ändern die View ``event_manager/events/views.py`` und ersetzen die Funktion ``category_detail`` mit dieser hier. Am Seitenanfang importieren wir noch ``get_object_or_404``.
.. code-block:: python
from django.shortcuts import get_object_or_404
def category_detail(request, slug: str):
"""
http://127.0.0.1:8000/events/category/sport
"""
category = get_object_or_404(Category, slug=slug)
return render(request, 'events/category_detail.html', {
'category': category
})
.. admonition:: get_object_or_404
Für die immerwiederkehrende Aufgabe, ein Objekt aus der Datenbank zu holen und per try-except zu prüfen, ob es in der Datenbank vorhanden ist, nutzen wir ab jetzt den Shortcut ``get_object_or_404``, den wir aus den ``django.shortcuts`` importieren. Wenn sich das Objekt nicht in der Datenbank befinden, wird ein 404-Fehler ausgelöst und dem User wird eine 404-Fehlerseite anzeigt.
Wir versuchen jetzt, die URL so aufzurufen:
http://127.0.0.1:8000/events/category/sport
Die Detailseite verlinken
-----------------------------------------------
Zuletzt wollen wir noch die Verlinkung auf die Kategorie bauen:
Ändern wir dazu ``event_manager/events/templates/events/category_list_simple.html`` noch ab.
.. code-block:: html+django
{% extends 'base.html' %}
{% block title %}
Übersicht der Kategorien
{% endblock %}
{% block head %}
Übersicht der Kategorien
{% endblock %}
{% block content %}
{% for cat in categories %}
-
{{cat.name}}
{% endfor %}
{% endblock %}
Pro Schleifendurchlauf bauen wir ein Listen-Elemente li, und setzen dort einen Hyperlink zu der jeweiligen Kategorie.
Der Hyperlink wird mit einem url-Tag entwickelt, der in der Form APP-Name:PFAD-Name angeben wird, sowie dahinter die jeweiligen Parameter.
Mehr dazu in der Doku:
``_
Verlinkungen mit dem URL-Tag
-----------------------------------------------
Einen templates-Tag, den wir noch nicht besprochen haben, ist der ``url``-Tag.
Dieser Tag ist dafür da, URLs zu generieren.
Der URL-Tag hat immer folgendes Schema:
..........................................
``{%url "" %}``
* APP_NAME: das entspricht der Variable ``app_name`` aus den ``urls.py`` der
App, also hier ``events`` (siehe Das Anlegen der ersten App).
* PATH_NAME: das enstpricht dem Name-Argument der path-Funktion aus den
App-Urls.
``path("category/", views.category_detail, name="category_detail")``
* PATH_ARGUMENTS: falls unsere Route einen oder mehrere Parameter definiert
hat, in unserem Fall also einen Slug, werden diese als leerzeichen-separierte Liste angegeben.
Mehr zum Thema ``url-Template Tag`` in der Django-Doku:
``_
.. admonition:: URL-Tag vs. hardkodierte URL
Wir erstellen die Verlinkungen über den ``url-Tag``, und das ist auch der
richtige Weg, dies zu tun. Wir könnten die Verlinkung natürlich auch direkt
hardkodiert erstellen, zb so:
``{{cat.slug}}``
Das würde gehen, gilt aber als schlechter Stil. Falls sich nämlich der
URL-Pfad der Route ändern würde, zum Beispiel von ``events/category`` zu
``events/genre``, müsste man den Link an allen Stellen, wo man ihn so
hardkodiert definiert hat, manuell ändern. Und diese Änderungen kommen häufiger vor, als man meinen würde.