Zum Inhalt springen
Vorschau auf das nächste Semester, noch nicht veröffentlicht.
Zur aktuellen Seite

Geburtstage

Aufgabe

So funktioniert ein Formular mit Umleitung

Die ganze App besteht aus einer Route, /. Sie beantwortet zwei Arten von Anfragen:

  1. Anzeigen (GET /): app.py liest birthdays.json ein und übergibt die Einträge an index.html. Jinja erzeugt daraus für jeden Eintrag eine Tabellenzeile.
  2. Absenden: Das Formular hat action="/" und method="post". Der Browser schickt die Felder als Paare aus name und Wert in einer POST-Anfrage an /. Alle Werte kommen als Strings an, auch aus Zahlenfeldern.
  3. Speichern (POST /): app.py liest die Felder mit request.form.get(…), ergänzt die Einträge um den neuen und schreibt alles zurück in birthdays.json.
  4. Umleiten: Statt eine Seite zu rendern, antwortet app.py mit redirect("/"). Der Browser fragt / daraufhin von selbst per GET an – weiter mit Schritt 1, jetzt mit dem neuen Eintrag.

Die Umleitung hat einen Grund: Lädt man die Seite danach neu, wiederholt der Browser nur das harmlose GET. Ohne Umleitung würde er das Formular (nach einer Rückfrage) noch einmal senden, und der Eintrag stünde doppelt in der Datei.

Beispiel: Die Datei ist leer, jemand trägt Harry mit dem 31. Juli ein.

Anfrage des BrowsersWas app.py tutbirthdays.json danachAntwort
GET /liest die Datei, rendert index.htmlleer ([])Formular und leere Tabelle
POST / mit name=Harry, month=7, day=31liest die Felder, ergänzt, speichertein Eintrag (Harry, 7, 31)Umleitung auf /
GET / (automatisch)liest die Datei, rendert index.htmlunverändertTabelle mit Zeile Harry, 7/31

Demo

birthdays

Aufgabenmaterial

Für diese Aufgabe werden Sie ein von uns zur Verfügung gestelltes Codegerüst vervollständigen.

Aufgabenmaterial herunterladen

Öffnen Sie VS CodeVisual Studio Code, der kostenlose Code-Editor von Microsoft, in dem Sie im Kurs programmieren. Glossar → entsprechend Ihrem Setup, klicken Sie auf Ihr Terminalfenster und führen Sie cd aus. Die EingabeaufforderungDas Zeichen am Anfang der Zeile im Terminal, etwa $ oder me/ $. Es zeigt, dass das Terminal auf Ihren nächsten Befehl wartet. Steht davor ein Ordnername wie me/, befinden Sie sich gerade in diesem Ordner. Glossar → Ihres Terminalfensters sollte ungefähr wie folgt aussehen:

$

Führen Sie den Befehl

wget https://dev.inf.zone/download/exercises/13/birthdays.zip

aus, um in Ihrem Codespace die ZIP birthdays.zip herunterzuladen.

Nun können Sie

unzip birthdays.zip

ausführen, um die ZIP in den Ordner birthdays zu entpacken.

Sie benötigen die ZIP-Datei nicht mehr, daher können Sie den Befehl

rm birthdays.zip

ausführen und bei der Aufforderung mit „y“ gefolgt von der Eingabetaste antworten, um die heruntergeladene ZIP-Datei zu entfernen.

Geben Sie nun den Befehl

cd birthdays

ein und drücken Sie anschließend die Eingabetaste, um in dieses Verzeichnis zu wechseln (d. h., es zu öffnen). Ihre Eingabeaufforderung sollte nun wie folgt aussehen:

birthdays/ $

Falls alles erfolgreich war, führen Sie den folgenden Befehl aus:

ls

Sie sollten nun die folgenden Dateien und Ordner sehen:

app.py  birthdays.json  static/  templates/

Falls es zu Problemen kommt, wiederholen Sie dieselben Schritte und versuchen Sie herauszufinden, wo ein Fehler aufgetreten sein könnte!

DateiInhalt
app.pydie Route / für GET und POST. Der POST-Zweig (nach dem if) leitet bisher nur auf / um, der GET-Zweig (nach dem else) rendert index.html ohne Daten. Fehlt birthdays.json, legt app.py die Datei beim Start mit einer leeren Liste an.
birthdays.jsondie Geburtstage, anfangs eine leere Liste ([])
static/styles.cssdas CSS der App – dürfen Sie ändern, müssen Sie aber nicht
templates/index.htmldie einzige Seite: Überschriften und eine Tabelle mit den Spalten „Name“ und „Birthday“. Kommentare mit TODO markieren, wo Formular und Tabellenzeilen hingehören.

Spezifikation

GET /: Geburtstage anzeigen

  • app.py: Lesen Sie die gespeicherten Geburtstage aus birthdays.json und übergeben Sie sie an render_template("index.html", …).
  • index.html: Geben Sie jeden Geburtstag als eine Zeile der Tabelle aus, mit zwei Spalten: Name der Person und Geburtstag (z. B. 7/31).

POST /: Geburtstag hinzufügen

  • index.html: Fügen Sie ein HTML-Formular hinzu, in das man einen Namen, einen Monat und einen Tag eingibt. Es sendet an / (action) mit der Methode POST.
  • app.py: Lesen Sie die Felder aus, fügen Sie den neuen Geburtstag zu den gespeicherten hinzu und schreiben Sie alles zurück in birthdays.json. Danach leitet die Route auf / um; redirect("/") steht schon im Gerüst.
  • Überlegen Sie sich, wie Sie einen Geburtstag in der Datei darstellen.

Optional

  • Geburtstage löschen und bearbeiten. Dafür lohnt es sich, jedem Eintrag eine ID zu geben.
  • Die Eingaben im Browser und im Server prüfen (client- und serverseitige Validierung).

Hilfestellung

Klicken Sie auf die folgenden Tipps, um einige Ratschläge zu erhalten. Versuchen Sie aber zunächst, selbst so weit wie möglich zu kommen.

JSON-Datei lesen und schreiben
  • json.load(f) liest den Inhalt einer geöffneten Datei f als Python-Wert ein, aus [] wird eine leere Liste.
  • json.dump(wert, f) schreibt einen Python-Wert in eine Datei, die Sie mit open(DATA_FILE, "w") geöffnet haben. "w" überschreibt die Datei; schreiben Sie also immer alle Einträge, nicht nur den neuen.
  • Für beides lohnen sich zwei kleine Funktionen, die Sie in beiden Zweigen der Route aufrufen.
Einen Geburtstag darstellen

Naheliegend ist eine Liste mit einem Dictionary je Geburtstag:

[
    {"name": "Harry", "month": "7", "day": "31"},
    {"name": "Ron", "month": "3", "day": "1"}
]

Ein neuer Geburtstag kommt dann mit append ans Ende der Liste.

Formular und Tabelle in index.html
  • Die name-Attribute der Eingabefelder (etwa name, month, day) sind die Schlüssel, unter denen request.form.get(…) die Werte findet.
  • Für Monat und Tag eignet sich <input type="number"> mit min und max; required verhindert leere Felder schon im Browser. Prüfen Sie im Server trotzdem, ob alle Felder ausgefüllt sind – eine POST-Anfrage lässt sich auch ohne Ihr Formular schicken.
  • Eine Tabellenzeile pro Eintrag erzeugen Sie mit einer Schleife in Jinja: {% for birthday in birthdays %} … {% endfor %}. Mit {{ birthday.name }} greifen Sie auch auf den Schlüssel eines Dictionarys zu.

Testen

Starten Sie den Server im Ordner birthdays:

flask run

app.py liest und schreibt birthdays.json in dem Ordner, in dem Sie flask run starten.

Prüfen Sie:

  • Tragen Sie einige Geburtstage ein. Erscheint jeder als eigene Zeile mit Name und Geburtstag?
  • Laden Sie die Seite nach dem Eintragen neu. Bleibt jeder Eintrag einfach, ohne Doppel?
  • Beenden Sie den Server (Strg+C) und starten Sie ihn neu. Sind die Einträge noch da? Stehen sie auch in birthdays.json?
  • Was passiert, wenn Sie ein Feld leer lassen?

Korrektheit

Führen Sie in Ihrem Terminal den folgenden Befehl aus, um die Korrektheit Ihrer Arbeit zu überprüfen:

check50 -l inf-zone/exercises/2026/birthdays

Abgeben

Geben Sie im Ordner birthdays ab:

inf upload birthdays

Danach sehen Sie, welche Tests Ihr Programm besteht und ob die Übung für die Bonuspunkte zählt. Wie Sie inf installieren und sich anmelden, steht unter Abgeben mit inf.

Diese Seite als Markdown: ansehen herunterladen