Kapitel 4. Webformulare
Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com
Die Templates, mit denen du in Kapitel 3 gearbeitet hast, sind unidirektional, d. h., sie ermöglichen den Informationsfluss vom Server zum Benutzer. Bei den meisten Anwendungen müssen die Informationen jedoch auch in die andere Richtung fließen, d. h. der Nutzer liefert Daten, die der Server annimmt und verarbeitet.
Mit HTML ist es möglich, Webformulare zu erstellen, in die die Benutzer Informationen eingeben können. Die Formulardaten werden dann vom Webbrowser an den Server übermittelt, normalerweise in Form einer POST
Anfrage. Das in Kapitel 2 vorgestellte Flask-Anfrageobjekt stellt alle vom Client in einer Anfrage gesendeten Informationen zur Verfügung und ermöglicht insbesondere bei POST
Anfragen, die Formulardaten enthalten, den Zugriff auf die Benutzerinformationen über request.form
.
Obwohl die Unterstützung durch das Request-Objekt von Flask für die Bearbeitung von Webformularen ausreichend ist, gibt es eine Reihe von Aufgaben, die mühsam und repetitiv werden können. Zwei gute Beispiele sind die Erstellung von HTML-Code für die Formulare und die Validierung der übermittelten Formulardaten.
Die Flask-WTF-Erweiterung macht die Arbeit mit Webformularen viel angenehmer. Diese Erweiterung ist ein Flask-Integrations-Wrapper um das Framework-agnostische WTForms-Paket.
Flask-WTF und seine Abhängigkeiten können mit pip installiert werden:
(venv) $ pip install flask-wtf
Konfiguration
Im Gegensatz zu den meisten anderen Erweiterungen muss Flask-WTF nicht auf der Anwendungsebene initialisiert werden, sondern erwartet, dass die Anwendung einen geheimen Schlüssel konfiguriert hat. Ein geheimer Schlüssel ist eine Zeichenkette mit beliebigem und eindeutigem Inhalt, die als Verschlüsselungs- oder Signierschlüssel verwendet wird, um die Sicherheit der Anwendung auf verschiedene Weise zu verbessern. Flask verwendet diesen Schlüssel, um den Inhalt der Benutzersitzung vor Manipulationen zu schützen. Du solltest für jede Anwendung, die du erstellst, einen anderen geheimen Schlüssel wählen und dafür sorgen, dass diese Zeichenfolge niemandem bekannt ist. Beispiel 4-1 zeigt, wie du einen geheimen Schlüssel in einer Flask-Anwendung konfigurierst.
Beispiel 4-1. hello.py: Flask-WTF Konfiguration
app
=
Flask
(
__name__
)
app
.
config
[
'SECRET_KEY'
]
=
'hard to guess string'
Das app.config
Wörterbuch ist ein allgemeiner Ort, um Konfigurationsvariablen zu speichern, die von Flask, Erweiterungen oder der Anwendung selbst verwendet werden. Konfigurationswerte können dem app.config
Objekt mit der Standard-Wörterbuchsyntax hinzugefügt werden. Das Konfigurationsobjekt verfügt auch über Methoden, um Konfigurationswerte aus Dateien oder der Umgebung zu importieren. Eine praktischere Möglichkeit, Konfigurationswerte für eine größere Anwendung zu verwalten, wird in Kapitel 7 behandelt.
Für Flask-WTF muss ein geheimer Schlüssel in der Anwendung konfiguriert werden, denn dieser Schlüssel ist Teil des Mechanismus, mit dem die Erweiterung alle Formulare vor Cross-Site-Request-Forgery (CSRF)-Angriffen schützt. Ein CSRF-Angriff erfolgt, wenn eine böswillige Website Anfragen an den Anwendungsserver sendet, auf dem der Benutzer gerade angemeldet ist. Flask-WTF erzeugt Sicherheits-Tokens für alle Formulare und speichert sie in der Benutzersitzung, die mit einer kryptografischen Signatur geschützt ist, die aus dem geheimen Schlüssel generiert wird.
Hinweis
Um die Sicherheit zu erhöhen, sollte der geheime Schlüssel in einer Umgebungsvariablen gespeichert werden, anstatt ihn in den Quellcode einzubauen. Diese Technik wird in Kapitel 7 beschrieben.
Klassen bilden
Bei der Verwendung von Flask-WTF wird jedes Webformular auf dem Server durch eine Klasse repräsentiert, die von der Klasse FlaskForm
erbt. Die Klasse definiert die Liste der Felder des Formulars, die jeweils durch ein Objekt dargestellt werden. Jedes Feldobjekt kann mit einem oder mehreren Validatoren versehen werden. Ein Validator ist eine Funktion, die überprüft, ob die vom Benutzer eingegebenen Daten gültig sind.
Beispiel 4-2 zeigt ein einfaches Webformular mit einem Textfeld und einem Submit-Button.
Beispiel 4-2. hello.py: Definition der Formularklasse
from
flask_wtf
import
FlaskForm
from
wtforms
import
StringField
,
SubmitField
from
wtforms.validators
import
DataRequired
class
NameForm
(
FlaskForm
):
name
=
StringField
(
'What is your name?'
,
validators
=
[
DataRequired
()])
submit
=
SubmitField
(
'Submit'
)
Die Felder im Formular sind als Klassenvariablen definiert, und jeder Klassenvariablen ist ein Objekt zugewiesen, das mit dem Feldtyp verknüpft ist. In diesem Beispiel hat das Formular NameForm
ein Textfeld mit dem Namen name
und einen Submit-Button mit dem Namen submit
. Die Klasse StringField
repräsentiert ein HTML <input>
Element mit einem type="text"
Attribut. Die Klasse SubmitField
steht für ein HTML-Element <input>
mit einem type="submit"
-Attribut. Das erste Argument der Feldkonstruktoren ist die Beschriftung, die beim Rendern des Formulars in HTML verwendet werden soll.
Das optionale Argument validators
im StringField
Konstruktor definiert eine Liste von Prüfern, die auf die vom Benutzer übermittelten Daten angewendet werden, bevor sie akzeptiert werden. Der DataRequired()
Validator stellt sicher, dass das Feld nicht leer übermittelt wird.
Hinweis
Die Basisklasse FlaskForm
wird von der Flask-WTF-Erweiterung definiert und daher von flask_wtf
importiert. Die Felder und Validatoren werden jedoch direkt aus dem WTForms-Paket importiert.
Die Liste der Standard-HTML-Felder, die von WTForms unterstützt werden, findest du in Tabelle 4-1.
Feldtyp | Beschreibung |
---|---|
|
Kontrollkästchen mit den Werten |
|
Textfeld, das einen |
|
Textfeld, das einen |
|
Textfeld, das einen |
|
Datei-Upload-Feld |
|
Verstecktes Textfeld |
|
Feld zum Hochladen mehrerer Dateien |
|
Liste der Felder eines bestimmten Typs |
|
Textfeld, das einen Gleitkommawert akzeptiert |
|
Formular eingebettet als Feld in einem Containerformular |
|
Textfeld, das einen ganzzahligen Wert annimmt |
|
Passwort-Textfeld |
|
Liste der Optionsfelder |
|
Dropdown-Liste mit Auswahlmöglichkeiten |
|
Dropdown-Liste mit Mehrfachauswahl |
|
Schaltfläche "Formular einreichen |
|
Textfeld |
|
Mehrzeiliges Textfeld |
Die Liste der in WTForms integrierten Validierer ist in Tabelle 4-2 aufgeführt.
Validator | Beschreibung |
---|---|
|
Prüft, ob das Feld nach der Typkonvertierung Daten enthält |
|
Bestätigt eine E-Mail-Adresse |
|
Vergleicht die Werte von zwei Feldern; nützlich, wenn ein Passwort zur Bestätigung zweimal eingegeben werden muss |
|
Prüft, ob das Feld vor der Typkonvertierung Daten enthält |
|
Überprüft eine IPv4-Netzwerkadresse |
|
Überprüft die Länge der eingegebenen Zeichenkette |
|
Überprüft eine MAC-Adresse |
|
Überprüft, ob der eingegebene Wert innerhalb eines numerischen Bereichs liegt |
|
Erlaubt leere Eingaben in das Feld und überspringt zusätzliche Überprüfungen |
|
Überprüft die Eingabe anhand eines regulären Ausdrucks |
|
Überprüft eine URL |
|
Überprüft eine UUID |
|
Überprüft, ob die Eingabe einer von mehreren möglichen Werten ist |
|
Überprüft, ob die Eingabe keiner der möglichen Werte ist |
HTML-Rendering von Formularen
Formularfelder sind Callables, die, wenn sie von einer Vorlage aufgerufen werden, sich selbst in HTML umwandeln. Angenommen, die View-Funktion übergibt der Vorlage eine NameForm
Instanz als Argument mit dem Namen form
, dann kann die Vorlage ein einfaches HTML-Formular wie folgt erzeugen:
<form
method=
"POST"
>
{{ form.hidden_tag() }} {{ form.name.label }} {{ form.name() }} {{ form.submit() }}</form>
Beachte, dass das Formular zusätzlich zu den Feldern name
und submit
ein Element form.hidden_tag()
enthält. Dieses Element definiert ein zusätzliches Formularfeld, das versteckt ist und von Flask-WTF verwendet wird, um CSRF-Schutz zu implementieren.
Natürlich ist das Ergebnis des Renderings eines Webformulars auf diese Weise extrem nackt. Alle Schlüsselwortargumente, die den Aufrufen zum Rendern der Felder hinzugefügt werden, werden in HTML-Attribute für das Feld umgewandelt. So kannst du dem Feld zum Beispiel die Attribute id
oder class
geben und dann CSS-Stile für sie definieren:
<form
method=
"POST"
>
{{ form.hidden_tag() }} {{ form.name.label }} {{ form.name(id='my-text-field') }} {{ form.submit() }}</form>
Aber selbst mit HTML-Attributen ist der Aufwand, der nötig ist, um ein Formular auf diese Weise darzustellen und es gut aussehen zu lassen, beträchtlich, daher ist es am besten, wenn du die Bootstrap-eigenen Formularstile verwendest, wann immer das möglich ist. Die Flask-Bootstrap-Erweiterung bietet eine High-Level-Hilfsfunktion, die ein komplettes Flask-WTF-Formular mit einem einzigen Aufruf mit den vordefinierten Formularstilen von Bootstrap rendert. Mit Flask-Bootstrap kann das vorherige Formular wie folgt gerendert werden:
{% import "bootstrap/wtf.html" as wtf %} {{ wtf.quick_form(form) }}
Die Direktive import
funktioniert genauso wie reguläre Python-Skripte und ermöglicht es, Template-Elemente zu importieren und in vielen Templates zu verwenden. Die importierte Datei bootstrap/wtf.html definiert Hilfsfunktionen, die Flask-WTF-Formulare mit Bootstrap darstellen. Die Funktion wtf.quick_form()
nimmt ein Flask-WTF-Formularobjekt und rendert es mit den Standard-Bootstrap-Styles. Das vollständige Template für hello.py ist in Beispiel 4-3 zu sehen.
Beispiel 4-3. templates/index.html: Verwendung von Flask-WTF und Flask-Bootstrap zur Darstellung eines Formulars
{% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky{% endblock %} {% block page_content %}<div
class=
"page-header"
>
<h1>
Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1>
</div>
{{ wtf.quick_form(form) }} {% endblock %}
Der Inhaltsbereich der Vorlage hat jetzt zwei Abschnitte. Der erste Abschnitt ist ein Seitenkopf, der eine Begrüßung zeigt. Hier wird ein Template Conditional verwendet. Konditionale Bedingungen in Jinja2 haben das Format {% if condition %}...{% else %}...{% endif %}
. Wenn die Bedingung den Wert True
ergibt, wird das, was zwischen den Direktiven if
und else
steht, der gerenderten Vorlage hinzugefügt. Wenn die Bedingung False
ergibt, wird stattdessen das, was zwischen else
und endif
steht, gerendert. Damit soll Hello, {{ name }}!
wiedergegeben werden, wenn die Template-Variable name
definiert ist, oder die Zeichenfolge Hello, Stranger!
, wenn sie nicht definiert ist. Der zweite Abschnitt des Inhalts rendert die Form NameForm
mit der Funktion wtf.quick_form()
.
Formularbehandlung in Ansichtsfunktionen
In der neuen Version von hello.py wird die Funktion index()
view zwei Aufgaben haben. Zuerst rendert sie das Formular und dann empfängt sie die vom Benutzer eingegebenen Formulardaten. Beispiel 4-4 zeigt die aktualisierte Funktion index()
view.
Beispiel 4-4. hello.py: ein Webformular mit GET- und POST-Methoden bearbeiten
@app.route
(
'/'
,
methods
=
[
'GET'
,
'POST'
])
def
index
():
name
=
None
form
=
NameForm
()
if
form
.
validate_on_submit
():
name
=
form
.
name
.
data
form
.
name
.
data
=
''
return
render_template
(
'index.html'
,
form
=
form
,
name
=
name
)
Das Argument methods
, das dem Dekorator app.route
hinzugefügt wird, weist Flask an, die View-Funktion als Handler für GET
und POST
Anfragen in der URL-Map zu registrieren. Wenn methods
nicht angegeben wird, wird die View-Funktion nur für die Bearbeitung von GET
Anfragen registriert.
Die Aufnahme von POST
in die Methodenliste ist notwendig, weil Formularübermittlungen viel bequemer als POST
Anfragen behandelt werden. Es ist zwar möglich, ein Formular als GET
Anfrage zu übermitteln, aber da GET
Anfragen keinen Body haben, werden die Daten als Query-String an die URL angehängt und sind in der Adressleiste des Browsers sichtbar. Aus diesem und anderen Gründen werden Formularübertragungen fast immer als POST
-Anfrage durchgeführt.
Die lokale Variable name
wird verwendet, um den vom Formular erhaltenen Namen zu speichern, wenn er verfügbar ist; wenn der Name nicht bekannt ist, wird die Variable auf None
initialisiert. Die View-Funktion erstellt eine Instanz der zuvor gezeigten Klasse NameForm
, um das Formular darzustellen. Die Methode validate_on_submit()
des Formulars gibt True
zurück, wenn das Formular abgeschickt wurde und die Daten von allen Feldüberprüfern akzeptiert wurden. In allen anderen Fällen gibt validate_on_submit()
False
zurück. Der Rückgabewert dieser Methode bestimmt, ob das Formular gerendert oder bearbeitet werden muss.
Wenn ein Benutzer zum ersten Mal zur Anwendung navigiert, erhält der Server eine GET
Anfrage ohne Formulardaten, so dass validate_on_submit()
False
zurückgibt. Der Body der if
Anweisung wird übersprungen und die Anfrage wird durch das Rendern der Vorlage bearbeitet, die das Formularobjekt und die name
Variable, die auf None
gesetzt ist, als Argumente erhält. Die Benutzer sehen nun das Formular im Browser angezeigt.
Wenn das Formular vom Benutzer abgeschickt wird, erhält der Server eine POST
Anfrage mit den Daten. Der Aufruf von validate_on_submit()
ruft den DataRequired()
Validator auf, der mit dem Namensfeld verbunden ist. Wenn der Name nicht leer ist, akzeptiert der Validator ihn und validate_on_submit()
gibt True
zurück. Jetzt ist der vom Benutzer eingegebene Name als data
Attribut des Feldes zugänglich. Im Textkörper der Anweisung if
wird dieser Name der lokalen Variable name
zugewiesen und das Formularfeld wird gelöscht, indem das Attribut data
auf eine leere Zeichenkette gesetzt wird, so dass das Feld leer ist, wenn das Formular wieder auf der Seite dargestellt wird. Der render_template()
Aufruf in der letzten Zeile rendert die Vorlage, aber dieses Mal enthält das name
Argument den Namen aus dem Formular, so dass die Begrüßung personalisiert wird.
Tipp
Wenn du das Git-Repository der Anwendung auf GitHub geklont hast, kannst du git checkout 4a
ausführen, um diese Version der Anwendung zu testen.
Abbildung 4-1 zeigt, wie das Formular im Browserfenster aussieht, wenn ein Nutzer die Website zum ersten Mal betritt. Wenn der Nutzer einen Namen eingibt, antwortet die Anwendung mit einer personalisierten Begrüßung. Das Formular erscheint immer noch darunter, so dass der Nutzer es auf Wunsch mehrmals mit verschiedenen Namen abschicken kann. Abbildung 4-2 zeigt die Anwendung in diesem Zustand.
Wenn der Benutzer das Formular mit einem leeren Namen absendet, fängt der DataRequired()
Validator den Fehler ab, wie in Abbildung 4-3 zu sehen ist. Beachte, wie viele Funktionen automatisch bereitgestellt werden. Dies ist ein großartiges Beispiel für die Leistungsfähigkeit, die gut durchdachte Erweiterungen wie Flask-WTF und Flask-Bootstrap deiner Anwendung verleihen können.
Umleitungen und Benutzersitzungen
Die letzte Version von hello.py hat ein Problem mit der Benutzerfreundlichkeit. Wenn du deinen Namen eingibst und abschickst und dann auf die Schaltfläche "Aktualisieren" in deinem Browser klickst, bekommst du wahrscheinlich eine obskure Warnung, die dich um Bestätigung bittet, bevor du das Formular erneut abschickst. Das passiert, weil Browser die letzte Anfrage wiederholen, die sie gesendet haben, wenn sie aufgefordert werden, eine Seite zu aktualisieren. Wenn es sich bei der letzten Anfrage um eine Anfrage mit Formulardaten handelt, würde eine Aktualisierung zu einer doppelten Übermittlung des Formulars führen, was in fast allen Fällen nicht erwünscht ist. Aus diesem Grund bittet der Browser um eine Bestätigung des Nutzers. POST
Viele Nutzer verstehen diese Warnung des Browsers nicht. Daher gilt es als gute Praxis für Webanwendungen, niemals eine POST
Anfrage als letzte Anfrage des Browsers zu hinterlassen.
Dies wird erreicht, indem auf POST
Anfragen mit einem Redirect anstelle einer normalen Antwort geantwortet wird. Ein Redirect ist eine besondere Art der Antwort, die eine URL anstelle einer Zeichenkette mit HTML-Code enthält. Wenn der Browser eine Redirect-Antwort erhält, stellt er eine GET
-Anfrage für die Redirect-URL, und das ist die Seite, die er anzeigt. Das ist die Seite, die angezeigt wird. Das Laden der Seite kann ein paar Millisekunden länger dauern, weil eine zweite Anfrage an den Server gesendet werden muss, aber ansonsten merkt der Nutzer keinen Unterschied. Jetzt ist die letzte Anfrage eine GET
, sodass der Refresh-Befehl wie erwartet funktioniert. Dieser Trick ist als Post/Redirect/Get-Muster bekannt.
Aber dieser Ansatz bringt ein zweites Problem mit sich. Wenn die Anwendung die Anfrage POST
bearbeitet, hat sie Zugriff auf den Namen, den der Nutzer in form.name.data
eingegeben hat. Sobald diese Anfrage jedoch endet, gehen die Formulardaten verloren. Da die POST
Anfrage mit einer Weiterleitung bearbeitet wird, muss die Anwendung den Namen speichern, damit die weitergeleitete Anfrage ihn erhalten und für die eigentliche Antwort verwenden kann.
Anwendungen können sich Dinge von einer Anfrage zur nächsten "merken", indem sie sie in der Benutzersitzung speichern, einer privaten Speicherung, die jedem verbundenen Client zur Verfügung steht. Die Benutzersitzung wurde in Kapitel 2 als eine der Variablen eingeführt, die mit dem Anfragekontext verbunden sind. Sie heißt session
und wird wie ein normales Python-Wörterbuch verwendet.
Hinweis
Benutzersitzungen werden standardmäßig in clientseitigen Cookies gespeichert, die mit dem konfigurierten geheimen Schlüssel kryptografisch signiert sind. Jegliche Manipulation des Cookie-Inhalts würde die Signatur ungültig machen und damit die Sitzung ungültig.
Beispiel 4-5 zeigt eine neue Version der index()
View-Funktion, die Redirects und Benutzersitzungen implementiert.
Beispiel 4-5. hello.py: Redirects und Benutzersitzungen
from
flask
import
Flask
,
render_template
,
session
,
redirect
,
url_for
@app.route
(
'/'
,
methods
=
[
'GET'
,
'POST'
])
def
index
():
form
=
NameForm
()
if
form
.
validate_on_submit
():
session
[
'name'
]
=
form
.
name
.
data
return
redirect
(
url_for
(
'index'
))
return
render_template
(
'index.html'
,
form
=
form
,
name
=
session
.
get
(
'name'
))
In der vorherigen Version der Anwendung wurde eine lokale Variable name
verwendet, um den vom Benutzer in das Formular eingegebenen Namen zu speichern. Diese Variable wird jetzt als session['name']
in der Benutzersitzung gespeichert, damit sie über die Anfrage hinaus erinnert wird.
Anfragen, die gültige Formulardaten enthalten, enden jetzt mit einem Aufruf von redirect()
, einer Flask-Hilfsfunktion, die die HTTP-Umleitungsantwort erzeugt. Die Funktion redirect()
nimmt die URL, zu der umgeleitet werden soll, als Argument entgegen. Die in diesem Fall verwendete Umleitungs-URL ist die Stamm-URL, so dass die Antwort auch als redirect('/')
hätte geschrieben werden können, aber stattdessen wird die in Kapitel 3 vorgestellte URL-Generatorfunktion url_for()
von Flask verwendet.
Das erste und einzige erforderliche Argument für url_for()
ist der Endpunktname, der interne Name, den jede Route hat. Standardmäßig ist der Endpunkt einer Route der Name der mit ihr verbundenen View-Funktion. In diesem Beispiel ist die View-Funktion, die die Root-URL verwaltet, index()
. Der Name von url_for()
ist also index
.
Die letzte Änderung betrifft die Funktion render_template()
, die jetzt das Argument name
direkt aus der Sitzung mit session.get('name')
abruft. Wie bei regulären Wörterbüchern vermeidet die Verwendung von get()
zur Abfrage eines Wörterbuchschlüssels eine Ausnahme für Schlüssel, die nicht gefunden werden. Die Methode get()
gibt bei einem fehlenden Schlüssel den Standardwert None
zurück.
Tipp
Wenn du das Git-Repository der Anwendung auf GitHub geklont hast, kannst du git checkout 4b
ausführen, um diese Version der Anwendung zu testen.
Mit dieser Version der Anwendung kannst du sehen, dass das Aktualisieren der Seite in deinem Browser immer zum erwarteten Verhalten führt.
Nachricht blinkt
Manchmal ist es sinnvoll, dem Nutzer eine Statusmeldung zu geben, nachdem eine Anfrage abgeschlossen ist. Das kann eine Bestätigungsmeldung, eine Warnung oder ein Fehler sein. Ein typisches Beispiel ist, wenn du ein Login-Formular auf einer Website mit einem Fehler abschickst und der Server daraufhin das Login-Formular erneut ausgibt und dir eine Meldung darüber gibt, dass dein Benutzername oder dein Passwort ungültig ist.
Flask enthält diese Funktion als Kernmerkmal. Beispiel 4-6 zeigt, wie die Funktion flash()
für diesen Zweck verwendet werden kann.
Beispiel 4-6. hello.py: geblitzte Nachrichten
from
flask
import
Flask
,
render_template
,
session
,
redirect
,
url_for
,
flash
@app.route
(
'/'
,
methods
=
[
'GET'
,
'POST'
])
def
index
():
form
=
NameForm
()
if
form
.
validate_on_submit
():
old_name
=
session
.
get
(
'name'
)
if
old_name
is
not
None
and
old_name
!=
form
.
name
.
data
:
flash
(
'Looks like you have changed your name!'
)
session
[
'name'
]
=
form
.
name
.
data
return
redirect
(
url_for
(
'index'
))
return
render_template
(
'index.html'
,
form
=
form
,
name
=
session
.
get
(
'name'
))
In diesem Beispiel wird jedes Mal, wenn ein Name eingegeben wird, dieser mit dem in der Benutzersitzung gespeicherten Namen verglichen, der dort bei einer früheren Eingabe desselben Formulars gespeichert wurde. Wenn die beiden Namen unterschiedlich sind, wird die Funktion flash()
mit einer Nachricht aufgerufen, die in der nächsten Antwort an den Kunden angezeigt wird.
Der Aufruf von flash()
reicht nicht aus, um die Meldungen anzuzeigen; die von der Anwendung verwendeten Templates müssen diese Meldungen auch darstellen. Der beste Ort für die Darstellung von Flash-Meldungen ist das Basis-Template, weil es diese Meldungen auf allen Seiten ermöglicht. Flask stellt den Templates eine get_flashed_messages()
Funktion zur Verfügung, um die Meldungen abzurufen und darzustellen, wie in Beispiel 4-7 gezeigt.
Beispiel 4-7. templates/base.html: Rendering von geblitzten Nachrichten
{% block content %}<div
class=
"container"
>
{% for message in get_flashed_messages() %}<div
class=
"alert alert-warning"
>
<button
type=
"button"
class=
"close"
data-dismiss=
"alert"
>
×
</button>
{{ message }}</div>
{% endfor %} {% block page_content %}{% endblock %}</div>
{% endblock %}
In diesem Beispiel werden die Meldungen mit den Bootstrap-CSS-Styles für Warnmeldungen dargestellt (eine davon ist in Abbildung 4-4 zu sehen).
Es wird eine Schleife verwendet, weil mehrere Nachrichten in der Warteschlange stehen können, eine für jeden Aufruf von flash()
im vorherigen Abfragezyklus. Meldungen, die von get_flashed_messages()
abgerufen werden, werden beim nächsten Aufruf dieser Funktion nicht mehr zurückgegeben, so dass geblinkte Meldungen nur einmal erscheinen und dann verworfen werden.
Tipp
Wenn du das Git-Repository der Anwendung auf GitHub geklont hast, kannst du git checkout 4c
ausführen, um diese Version der Anwendung zu testen.
Die Möglichkeit, Daten vom Benutzer über Webformulare entgegenzunehmen, ist eine Funktion, die von den meisten Anwendungen benötigt wird, ebenso wie die Möglichkeit, diese Daten in einer permanenten Speicherung abzulegen. Die Verwendung von Datenbanken mit Flask ist das Thema des nächsten Kapitels.
Get Flask Web Development, 2. Auflage now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.