Hello, Flask
Lernziele
- Erstellen Sie eine einfache Flask-Anwendung, um ein Verständnis dafür zu entwickeln, wie man dieses Framework verwendet.
- Machen Sie sich mit Jinja vertraut, einer Template-Sprache, die in Verbindung mit Flask genutzt wird.
Hintergrund
Flask, ein Microframework für die Webentwicklung, kann zu Beginn verwirrend sein. Es gibt mehrere Dateien unterschiedlichen Typs, die in bestimmten Ordnern abgelegt werden müssen. In diesem Problem beginnen wir mit dem absoluten Minimum – einer einzelnen Python-Datei. Von dort aus werden wir den nächsten Schritt machen und unsere erste vollwertige Webanwendung erstellen!
Bevor Sie beginnen
Öffnen Sie VS Code entsprechend Ihrem Setup, klicken Sie auf Ihr Terminalfenster und führen Sie cd
aus. Die Eingabeaufforderung Ihres Terminalfensters sollte ungefähr wie folgt aussehen:
$
Führen Sie den Befehl
wget https://inf.zone/download/exercises/09/helloflask.zip
aus, um in Ihrem Codespace die ZIP helloflask.zip
herunterzuladen.
Nun können Sie
unzip helloflask.zip
ausführen, um die ZIP in den Ordner helloflask
zu entpacken.
Sie benötigen die ZIP-Datei nicht mehr, daher können Sie den Befehl
rm helloflask.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 helloflask
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:
helloflask/ $
Implementierungsdetails
Die einfachste Flask-Anwendung verwendet nur eine Datei, app.py
. Diese erstellt eine HTML-Seite und sagt “Hallo”. Fügen Sie Folgendes in app.py
ein, um zu beginnen:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello, World!"
Dieser Code beginnt damit, Flask
aus der flask
-Bibliothek zu importieren. Flask ist eine Klasse (siehe Short zum Objektorientierten Programmieren. Es reicht vorerst zu sagen, dass es wie eine Vorlage für die Anwendung ist, die wir erstellen werden. Die Zeile app = Flask(__name__)
weist Python an, eine bestimmte Anwendung zu erstellen, die, basierend auf der Vorlage, fortan „app“ genannt wird. Um die spezifische Anwendung zu erstellen, übergeben wir der Flask-Klasse den Namen der aktuellen Python-Datei (repräsentiert durch __name__
), was es unserer Anwendung ermöglicht, später hinzugefügte Dateien zu finden. In diesem Fall heißt die Datei ebenfalls „app“, um konsistent zu bleiben.
Die mysteriöseste Zeile in der von Ihnen geschriebenen Anwendung ist wahrscheinlich die, in der Sie folgendes geschrieben haben:
@app.route("/")
Diese Art von Funktion wird als Dekorator bezeichnet. Dekoratoren ermöglichen es, eine grundlegende Funktion wie app.route
zu nehmen und deren Funktionalität mit etwas Eigenem zu erweitern: der Funktion, die Sie nach dem Dekorator schreiben. Wenn Sie mehr über Dekoratoren erfahren möchten, können Sie entsprechende Ressourcen dazu lesen oder das Short zum Objektorientierten Programmieren ansehen (@property ist auch ein Decorator).
Diese Zeile teilt Flask mit, dass, wenn eine HTTP-Anfrage für „/“ eingeht, die Funktion index
ausgeführt werden soll. Beachten Sie, dass, wenn wir die Funktion in homepage
umbenennen würden, diese Zeile Flask mitteilen würde, dass es, jedes Mal, wenn es eine HTTP-Anfrage für „/“ erhält, die Funktion homepage
ausführen soll.
Beachten Sie, dass die Funktion index
ein Textstück, nämlich „Hello, World!“, zurückgibt. Dieser Text wird dem Benutzer von Flask angezeigt, sobald ihre Anfrage an die „/“-Route abgeschlossen ist. Statt eines einfachen Textstücks könnte die Funktion auch den Inhalt einer vollständigen HTML-Datei zurückgeben, die der Browser entsprechend rendern würde – dies ist in der Praxis häufig der Fall. Der Einfachheit halber beschränken wir uns jedoch zunächst auf diesen kurzen Text.
Um Ihre Anwendung auszuführen, geben Sie flask run
in das Terminal ein, und Sie erhalten einen Link, auf den Sie klicken können, ähnlich wie bei der Ausführung von http-server
. Sie haben eine Flask-Anwendung geschrieben! Versuchen Sie, einen anderen Text zurückzugeben, wie <h1>Hello, World!</h1>
. Wie verändert sich das, was Sie sehen?
Templates
Anstatt HTML-Code direkt in unsere Python-Programme einzufügen, ist es am besten, unser HTML in separate Dateien auszulagern, um die verschiedenen Aufgaben zu trennen. Da unsere App wahrscheinlich eine Reihe ähnlicher HTML-Dateien beinhalten wird, können wir eine Datei namens layout.html
erstellen, die alle unsere HTML-Dateien „erweitern“. Das „Erweitern“ einer HTML-Datei bedeutet, dass der gesamte Inhalt dieser HTML-Datei beibehalten wird, während zusätzlich benutzerdefinierter Inhalt eingefügt wird, der spezifisch für eine bestimmte Seite ist.
Nach Konvention speichert Flask alle HTML-Dateien in einem Ordner namens templates
. Erstellen Sie im Ordner helloflask
einen Ordner namens templates
, indem Sie mkdir templates
ausführen. Alle Ihre HTML-Dateien werden in diesem Ordner abgelegt.
Erstellen Sie im Ordner templates
eine Datei namens layout.html
, die wie folgt aussieht:
<!DOCTYPE html>
<html lang="de">
<head>
<title>Hallo, Flask</title>
</head>
<body>
<h1>Hallo, Flask</h1>
{% block body %}{% endblock %}
</body>
</html>
Die Syntax {% block body %}{% endblock %}
stammt von Jinja, einer „Template-Engine“ für Python. Die Zeile mit {% block body %}{% endblock %}
macht diese Datei zu einer Layout-Datei. Wenn eine andere HTML-Datei die Datei layout.html
erweitert und einen Block namens „body“ definiert, wird dieser Block an dieser Stelle in der layout.html
eingefügt. Eine Layout-Datei kann so viele Blöcke enthalten, wie man möchte. Geben Sie einfach jedem Block einen anderen Namen.
Erstellen Sie nun eine Datei index.html
, die das Template layout.html
wie folgt erweitert:
{% extends "layout.html" %}
{% block body %}
<p>Als Nächstes fügen wir hier ein Formular ein und erhalten eine POST-Aktion!</p>
{% endblock %}
Zuletzt kehren wir zu app.py
zurück, um diese Änderungen umzusetzen. In den anfänglichen Importen benötigen wir einige weitere Funktionen aus Flask (wie unten gezeigt). Ersetzen Sie dann die direkte Rückgabe von Text durch einen Aufruf der Funktion render_template
von Flask. Der Zweck der Funktion render_template
ist es, index.html
so vorzubereiten, dass sie beim Übergeben an den Browser auch das HTML enthält, das sie von layout.html
„erbt“.
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
Wenn Sie nun Ihre Anwendung ausführen (geben Sie flask run
ein), wird Ihre App ein wenig strukturierter. Aber sie ist noch nicht wirklich interaktiv!
Forms
HTML-Forms ermöglichen es dem Benutzer, Daten in Eingabefelder einzugeben und diese Daten an den Server zu senden, häufig unter Verwendung der POST-Methode des HTTP-Protokolls. Weitere Informationen zu HTML-Forms finden Sie hier.
Fügen Sie ein Form zu index.html
hinzu, sodass es wie folgt aussieht:
{% extends "layout.html" %}
{% block body %}
<form action="/" method="post">
Was ist Ihre Lieblingsfarbe?
<select name="color">
<option value="red">Harvard Crimson</option>
<option value="blue">Yale Blue</option>
</select>
<button type="submit">Absenden</button>
</form>
{% endblock %}
Beachten Sie, dass jedes Formularelement sowohl einen name als auch ein value hat. Der Name eines Elements ist das, worüber wir dieses Element ansprechen werden. Sein Wert ist der Wert, der vom Formular übermittelt wird. Jeder dieser Werte wird an app.py
übergeben, damit wir ihn beim Absenden des Formulars nutzen können.
Führen Sie Ihre Anwendung aus, besuchen Sie die /
-Route und senden Sie das Formular ab. Ups! Sie sollten die Nachricht „Methode nicht erlaubt“ sehen. Daher müssen wir zunächst sicherstellen, dass Flask die Verwendung der POST-Methode auf /
zulässt.
POST
In der Datei app.py
müssen wir unsere Route anpassen, um die POST-Anfrage zu verarbeiten. So sieht unser neues app.py
aus:
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "GET":
return render_template("index.html")
else:
print("Formular wurde abgesendet!")
color = request.form.get("color")
return render_template("color.html", color=color)
Dieses Beispiel enthält einige Logik: Wenn der Benutzer eine GET-Anfrage sendet, zeigen wir ihm das grundlegende index.html
mit einem Formular zum Absenden. Wenn jedoch eine POST-Anfrage gesendet wird, tun wir einige unterschiedliche Dinge:
- Wir geben die Nachricht „Formular wurde abgesendet!“ in der Konsole aus, um das Debuggen zu erleichtern. Wir sollten dies später entfernen, wenn wir sicher sind, dass unser Programm wie gewünscht funktioniert.
- Der Wert der „color“-Eingabe wird in einer Variablen mit dem gleichen Namen gespeichert, also mit
color = request.form.get("color")
. - Eine neue HTML-Datei,
color.html
, wird gerendert und der Wert dercolor
-Variablen wird unter dem gleichen Namen in die Datei übergeben.
Erstellen wir nun color.html
, damit unsere Anwendung funktioniert:
{% extends "layout.html" %}
{% block body %}
<p style="color: {{ color }}">Ihre Lieblingsfarbe ist {{ color }}.</p>
{% endblock %}
Beachten Sie, wie wir den Wert von color
an jeder beliebigen Stelle in unserem HTML einfügen können – sei es als Text in einem Satz oder als Platzhalter für den Wert einer CSS-Eigenschaft.
Wir möchten jedoch wahrscheinlich eine zusätzliche Eingabevalidierung hinzufügen, anstatt einfach darauf zu vertrauen, dass unsere Benutzer nur die Farben „blau“ oder „rot“ über POST senden. Welchen zusätzlichen Code könnten Sie hinzufügen, um sicherzustellen, dass die Farben, die wir erhalten, gültige Farben sind?
Testen
Ihr Programm sollte sich gemäß den oben genannten Beispielen verhalten.
Für diese Aufgabe gibt es kein check50
!