Drei Aufgaben zur Wahl
Die drei Aufgaben sind voneinander unabhängig. Keine baut auf einer anderen auf, keine schließt eine andere aus, und es gibt keine Reihenfolge. Nimm eine, nimm zwei, nimm alle drei – oder bleib bei einer und mach sie gründlich.
python manage.py check, dann python manage.py test,
dann python manage.py runserver. Wenn das jetzt grün ist, weißt du
später, dass ein Fehler von deiner Änderung kommt.
leicht 1 · Lesedauer auf der Buchseite
Zwei Dateien, keine Datenbankänderung. Wer zügig arbeitet, ist in einer halben Stunde fertig.
Worum es geht
Auf der Detailseite eines Buchs steht die Seitenzahl. Daraus lässt sich eine geschätzte Lesedauer errechnen – rechne mit rund 45 Seiten pro Stunde. Diese Schätzung soll als eigene Zeile auf der Buchseite erscheinen.
Fertig ist es, wenn
- auf
/buecher/<id>/eine Zeile Lesedauer steht, - dort etwas wie ca. 6 h 30 min erscheint, passend zur Seitenzahl,
- und ein Buch mit 0 Seiten keine kaputte Ausgabe erzeugt.
Dateien, die du anfasst
| Datei | Was dort hinkommt |
|---|---|
bibliothek/templatetags/bibliothek_extras.py | ein neuer Filter |
bibliothek/templates/bibliothek/buch_detail.html | eine neue Zeile in der Datenliste |
Schritte
- Sieh dir in
bibliothek_extras.pydie vorhandenen Filtersterneundtage_bisan. Dein Filter folgt demselben Muster. - Schreibe einen Filter, der aus einer Seitenzahl einen Text macht. Der Dekorator
darüber lautet
@register.filter. - Server neu starten. Änderungen an Template-Tags werden beim Laden gefunden, nicht bei jedem Aufruf.
- Ergänze in
buch_detail.htmlinnerhalb der Liste<dl class="daten">ein Paar aus<dt>und<dd>und wende deinen Filter aufbuch.seitenan. Wie das aussieht, zeigt die Zeile mit der Bewertung direkt darüber.
Stolpersteine
{% load bibliothek_extras %}steht in dieser Vorlage schon oben – du brauchst es nicht noch einmal.- Ein Filter, der nichts zurückgibt, liefert eine leere Zeile statt eines Fehlers.
Wenn nichts erscheint, prüfe zuerst das
return. - Teilen durch Null: Bücher mit
seiten = 0gibt es im Bestand.
Im Buch: Templates und ihre Erweiterungen
mittel 2 · Seiten für Kategorien
Zwei neue Sichten, zwei neue Vorlagen, keine Datenbankänderung. Etwa eine Stunde.
Worum es geht
Die Kategorien tauchen bisher nur als Filterleiste über der Buchliste auf. Sie sollen eigene Seiten bekommen: eine Übersicht aller Kategorien mit der Zahl ihrer Bücher, und pro Kategorie eine Seite mit den zugehörigen Büchern.
Fertig ist es, wenn
/kategorien/alle Kategorien auflistet, jede mit der Anzahl Bücher,- ein Klick auf eine Kategorie zu
/kategorien/fantasy/führt, - dort die Bücher dieser Kategorie stehen,
- und eine unbekannte Kategorie einen 404 ergibt und keinen Serverfehler.
Dateien, die du anfasst
| Datei | Was dort hinkommt |
|---|---|
bibliothek/views.py | zwei Sichten |
bibliothek/urls.py | zwei Routen mit Namen |
bibliothek/templates/bibliothek/ | zwei neue Vorlagen |
templates/base.html | optional ein Eintrag in der Navigation |
Schritte
- Schau dir
autor_listeinviews.pyan. Deine Kategorieübersicht ist dieselbe Bauform: abfragen, an eine Vorlage geben. - Die Anzahl der Bücher hängst du mit
annotatean jede Kategorie. Wie das geht, steht in derselben Datei beiautor_liste. - Für die Detailseite brauchst du die Kategorie anhand ihres Slugs. Nimm
get_object_or_404; die Bücher erreichst du über den Rückweg der Beziehung, denrelated_nameim Modell festlegt. - Trage beide Routen in
bibliothek/urls.pyein und gib ihnen einenname. Für den Slug ist der Konverter<slug:...>zuständig. - Die Vorlagen beginnen mit
{% extends "base.html" %}. Für die Buchkarten kannst du{% buch_karte buch %}wiederverwenden – das gibt es schon.
Stolpersteine
- Verweise auf eigene Seiten brauchen den App-Namensraum:
{% url 'bibliothek:kategorie-detail' ... %}. Ohnebibliothek:gibt es einNoReverseMatch. - Die Reihenfolge in
urlpatternszählt: Der erste Treffer gewinnt. - Wenn du
buch_kartebenutzt, muss oben in deiner Vorlage{% load bibliothek_extras %}stehen.
Im Buch: Der ORM und seine QuerySets, Views zwischen Funktion und Klasse, Vom WSGI-Aufruf bis zur Antwort
höher 3 · Wunschliste
Ein neues Modell samt Migration, Formular, Sicht, Vorlage, Admin und einem Test. Zwei Stunden, eher mit Pausen.
Worum es geht
Angemeldete Personen sollen Bücher vormerken können, die es im Bestand noch gar nicht gibt: Titel, eine kurze Begründung, fertig. Jede sieht ihre eigenen Wünsche, die Bibliothek sieht im Admin alle. Die Wunschliste hängt an keinem vorhandenen Modell – sie kommt neu dazu und kollidiert deshalb mit nichts.
Fertig ist es, wenn
/wuensche/nach Anmeldung ein Formular und die eigenen Wünsche zeigt,- ein abgeschickter Wunsch in der Liste erscheint und eine Erfolgsmeldung kommt,
- ein leerer Titel abgelehnt wird, mit Meldung am Feld,
- die Wünsche im Admin unter
/admin/auftauchen, - abgemeldet ein Aufruf von
/wuensche/zur Anmeldeseite führt, - und
python manage.py testgrün bleibt – inklusive eines eigenen Tests.
Dateien, die du anfasst
| Datei | Was dort hinkommt |
|---|---|
bibliothek/models.py | ein Modell Wunsch |
bibliothek/migrations/ | wird erzeugt, nicht geschrieben |
bibliothek/forms.py | ein ModelForm |
bibliothek/views.py | eine Sicht für Anzeigen und Anlegen |
bibliothek/urls.py | eine Route |
bibliothek/templates/bibliothek/ | eine Vorlage |
bibliothek/admin.py | eine ModelAdmin |
bibliothek/tests.py | ein Test |
Schritte
- Modell. Felder: Titel, Begründung, wer es wünscht, wann angelegt.
Für die Person verweist du nicht direkt auf
User, sondern aufsettings.AUTH_USER_MODEL– wie esAusleihevormacht. Vergiss__str__und dieMeta-Angaben nicht. - Migration.
python manage.py makemigrations, die erzeugte Datei einmal lesen, dannpython manage.py migrate. Beides ist nötig. - Formular. Ein
ModelFormmit den Feldern, die eine Person selbst eintippt – also ohne Person und ohne Zeitstempel.BuchFormundAusleiheFormsind die Vorbilder. - Sicht. Eine Funktion mit
@login_required, die bei GET das Formular und die eigenen Wünsche zeigt und bei POST speichert. Die Person setzt du selbst, mitform.save(commit=False). Genau dieses Muster steht inausleihen. - Route und Vorlage wie gewohnt, mit
nameundextends "base.html". - Admin. Eine Klasse mit
@admin.register(Wunsch)und ein paar Spalten inlist_display. - Test. Einer genügt: anmelden, Wunsch abschicken, prüfen, dass er in
der Datenbank steht.
test_anlegen_mit_loginintests.pyzeigt die Bauform.
Stolpersteine
makemigrationsallein ändert nichts an der Datenbank. Ohnemigratekommt beim Aufruf no such table.- Ein neues Feld ohne
defaultund ohnenull=Trueführt zu einer Rückfrage vonmakemigrations. Beantworte sie nicht raten – brich ab und setze einen Standardwert. save()prüft nicht. Dass ein leerer Titel abgelehnt wird, leistet das Formular, nicht das Modell.- Zeige nur die eigenen Wünsche. Ein Filter auf
request.usergehört in die Abfrage, nicht in die Vorlage.
Im Buch: Das Datenmodell, Formulare und Validierung, Der Admin als generierte Oberfläche
KI sinnvoll einsetzen
Für alle drei Aufgaben ist eine KI ein gutes Werkzeug – wenn du sie führst und nicht umgekehrt. Was in der Praxis den Unterschied macht:
- Gib die echte Datei mit, nicht deine Beschreibung davon. Die Vorbilder
stehen alle im Projekt; eine KI, die
views.pygesehen hat, schlägt Code vor, der zu diesem Projekt passt. - Bitte um die kleinste Änderung, nicht um eine neue Fassung der Datei. Wer eine ganze Datei zurückbekommt, kann nicht mehr sehen, was sich geändert hat.
- Lass dir jede Zeile erklären. Am Nachmittag sollst du deine Änderung der Runde erklären können. Das ist der eigentliche Test, nicht das Laufen des Codes.
- Prüfe selbst im Browser gegen die Liste „Fertig ist es, wenn". Die KI sieht deinen Bildschirm nicht und weiß nicht, ob es funktioniert hat.
- Rechne mit veralteten Vorschlägen. Django ändert Details zwischen den Versionen. Wenn ein Vorschlag nicht läuft, ist die Version der häufigste Grund – welche hier gilt, steht in der Fußzeile dieser Seite.
Wenn etwas klemmt
| Meldung | Erste Maßnahme |
|---|---|
no such table | python manage.py migrate |
NoReverseMatch | Name und Namensraum im url-Tag prüfen |
TemplateDoesNotExist | Pfad der Vorlage prüfen: <app>/templates/<app>/… |
is not a registered tag library | Server neu starten |
| Seite bleibt leer, kein Fehler | Schreibweise der Variablen im Template prüfen |
| Formular speichert nichts, keine Meldung | {{ form.errors }} ins Template |
Alles zurücksetzen, was du geändert hast: git checkout -- . verwirft die
Änderungen an den Dateien, python manage.py migrate bibliothek 0001 setzt die
Datenbank auf den Ausgangsstand zurück.