25.8 Verarbeitung von Formulardaten 

Um eine dynamische Webanwendung wirklich interaktiv werden zu lassen, müssen die Benutzer neben dem einfachen Navigieren über die Seite auch zum Inhalt der Seite beitragen können. Dies geschieht oft über Gästebücher, Foren oder Kommentarfunktionen wie in unserem Beispiel.
Auf der technischen Seite muss für diese Funktionalitäten eine Schnittstelle existieren, mit der Daten vom Browser des Benutzers an die Serveranwendung übertragen werden können.
Das HTTP-Protokoll bietet für diesen Zweck zwei Methoden für die sogenannte Argumentübertragung an: GET und POST. Der prinzipielle Unterschied zwischen den beiden Übertragungsarten ist, dass mit GET übertragene Daten direkt an die Adresse der jeweiligen Seite angehängt werden und so für den Benutzer unmittelbar sichtbar sind, während die POST-Methode für den Benutzer unsichtbar im Hintergrund Daten übertragen kann.
Beide Methoden arbeiten mit benannten Platzhaltern, die üblicherweise durch HTML-Formulare mit Daten verknüpft werden.
Unser Formular für die Kommentarabgabe
Wir werden auf der Detailseite jeder Meldung ein Formular anbieten, in dem der Besucher neue Kommentare zu der angezeigten Meldung eingeben kann. Das Formular wird zwei Textfelder besitzen: eines für den Namen des Besuchers und eines für den Kommentar selbst. Im Browser soll es später so aussehen wie in Abbildung 25.15.
Abbildung 25.15 Unser Kommentarformular
Als Übertragungsart für die eingegebenen Daten wählen wir die POST-Methode, um die Adressleiste nicht zu überfüllen. Das Speichern der neuen Kommentare wird unsere View-Funktion meldung_detail übernehmen, der beim Abschicken des Formulars ein GET-Parameter namens speichere_kommentar übergeben wird. Außerdem soll das Formular ein Feld für Fehlerausgaben besitzen, falls der Benutzer zu wenige Angaben gemacht hat.
Das Template für die Formulardefinition sieht dann folgendermaßen aus: [Dieser Teil muss unten in der meldung_detail.html eingefügt werden. Die vollständige Template-Datei finden Sie auf der Buch-CD. ]
<div class="kontainer"> <div class="titelzeile">Neuer Kommentar</div> <span class="fehler">{{ fehler }}</span> <form method="post" action="?kommentar_speichern"> <table> <tr class="kommentarzeile"> <td class="spaltenbezeichner">Ihr Name:</td> <td><input type="text" name="besuchername" value="{{ bentzername }}"/></td> </tr> <tr class="kommentarzeile"> <td class="spaltenbezeichner">Kommentar:</td> <td> <textarea name="kommentartext"> {{ kommentar }} </textarea> </td> </tr> </table> <input type="submit" value="Abschicken" /> </form> </div>
Wie Sie der Zeile <form method="post" action="?kommentar_speichern"> entnehmen können, wird beim Versenden des Formulars die Detailseite der Meldung mit dem GET-Parameter kommentar_speichern aufgerufen. Außerdem werden die Werte der Textfelder besuchername und kommentartext als POST-Daten übergeben.
Sollten beim Speichern eines Kommentars Fehler auftreten, kann eine Meldung über die Kontextvariable fehler von der View-Funktion gesetzt werden. Damit die Eingaben des Benutzers in einem solchen Fall nicht verloren gehen, können die Textfelder über die Kontextvariablen benutzername und kommentar von der View mit Initialwerten versehen werden.
Zugriff auf POST- und GET-Variablen in View-Funktionen
Wie Sie bereits wissen, bekommt jede View-Funktion von Django einen Parameter namens request übergeben. Dieser Parameter enthält Informationen über den Seitenaufruf und damit insbesondere die GET- und POST-Parameter. Dazu hat request zwei Attribute namens GET und POST, die den Zugriff auf die Parameter über ihre Namen wie in einem Dictionary ermöglichen.
Mit diesem Wissen können wir unsere View-Funktion model_detail folgendermaßen erweitern (die noch nicht bekannten Elemente im Listing werden anschließend erläutert):
def meldung_detail(request, meldungs_id): meldung = get_object_or_404(Meldung, id=meldungs_id) if "kommentar_speichern" in request.GET: name = request.POST.get("besuchername", "") text = request.POST.get("kommentartext", "") if name and text: kommentar = meldung.kommentar_set.create( autor=name, text=text) kommentar.save() return HttpResponseRedirect(".") else: return render_to_response("news/meldung_detail.html", {"meldung" : meldung, "fehler": "Sie müssen Ihren Namen und \ einen Kommentar angeben.", "besuchername" : name, "kommentartext" : text}) return render_to_response("news/meldung_detail.html", {"meldung" : meldung})
Am Anfang der Funktion lesen wir wie gehabt die betreffende Meldung aus der Datenbank oder geben einen Http404-Fehler zurück. Anschließend prüfen wir mit dem in-Operator, ob "kommentar_speichern" per GET übergeben worden ist, um gegebenenfalls einen neuen Kommentar zu speichern. Wurde "kommentar_speichern" nicht übergeben, wird der if-Block ausgelassen und die Detailseite angezeigt.
Wenn ein neuer Kommentar gespeichert werden soll, lesen wir den eingegebenen Namen und den Kommentartext aus request.POST. Anschließend prüfen wir, ob in beide Textfelder etwas eingegeben wurde. Fehlt mindestens eine Angabe, wird im else-Zweig die Detailseite erneut angezeigt, wobei ein entsprechender Fehlertext ausgegeben wird. Dadurch, dass wir die Kontext-Variablen besuchername und kommentartext auf die zuvor übergebenen Werte setzen, gehen eventuell vom Benutzer gemachte Eingaben nicht verloren, sondern erscheinen wieder in den Textfeldern.
Haben die beiden Variablen name und text korrekte Werte, erzeugen wir ein neues Kommenter-Objekt in der Datenbank. Allerdings benutzen wir in diesem Fall die Klasse HttpResponseRedirect, um den Besucher zu der Detailseite weiterzuleiten, anstatt ein Template auszugeben. Der Grund dafür ist einfach: Wenn ein Besucher einen neuen Kommentar verfasst hat und nun wieder auf der Detailseite gelandet ist, könnte er die Aktualisieren-Funktion seines Browsers benutzen, um die Seite neu zu laden. Beim Aktualisieren einer Seite werden aber sowohl GET- als auch POST-Daten erneut übertragen. Deshalb würde bei jeder Aktualisierung derselbe Kommentar noch einmal gespeichert werden. Durch die indirekte Weiterleitung mittels HttpResponseRedirect lösen wir dieses Problem, da nun die POST- und GET-Variablen verworfen werden.
Sie können HttpResponseRedirect per import aus dem Modul django.http einbinden.
Nun ist unsere Beispielanwendung vollständig funktionsfähig. Wenn Sie Ihre Django-Kenntnisse vertiefen möchten, um auch die weiterführenden Techniken kennenzulernen, empfehlen wir Ihnen die Lektüre der ausgezeichneten Online-Dokumentation auf der Django-Homepage unter http://www.djangoproject.com.