Python: Webseiten mit Flask

Flask ist ein Webframework, mit dessen Hilfe wir dynamische Webseiten mit Python erstellen können.

1Python Programmierkurs
2Python: Methoden
3Kontrollstrukturen
4Strings in Python
5Container
6Objekte in Python
7Module
8Exceptions in Python
9Typkonvertierung
10Python und Dateien
11Datum und Zeit mit Python verarbeiten
12Multithreading
13Netzwerk in Python
14Logging in Python
15GPIO
16Automatische Tests
17Datenbanken mit Python
18Python: Generatoren und List Comprehension
19Python: Webseiten mit Flask
20Python virtuelle Umgebungen
21Interrupts & Signale
22NumPy
23Matplotlib
24match
Python Logo (CC-BY-SA The people from the Tango! project / Wikipedia)
Python Logo (CC-BY-SA The people from the Tango! project / Wikipedia)

Flask installieren

Unter DietPi gibt es zwei Möglichkeiten, die Flask Umgebung zu installieren.

Entweder über die Paketverwaltung des Betriebssystems

sudo apt install python3-flask

Oder über den Python Paketmanager

pip install flask

Eine einfache Flask App

Wir fangen zunächst mal ganz einfach an, indem wir uns von unserer Flask-App einfach nur einen String zurückliefern lassen, den der Browser ausgibt.

Schauen wir uns das Programm mal an:

from flask import Flask


app = Flask(__name__)

@app.route('/')

def index():
  return 'Ein erstes Hallo'

if __name__ == '__main__':
  app.run(host='0.0.0.0',port=8085, debug=True)

Eine Flask-App wird immer mit

app = Flask(__name__)

initialisiert und dann mit

f __name__ == '__main__':
  app.run(host='0.0.0.0',port=8085, debug=True)

gestartet. Mehr brauchst du nicht, um einen Webserver aufzubauen, der auf Port 8085 auf eingehende Requests wartet. Wichtig ist noch die Zeile @app.route('/') über der Methode index(). Sie dekoriert die Methode index() so, dass Flask sie dem Request mit dem URL http://<hostname>:8085 zuordnet und aufruft.

Du könntest jetzt eine weitere Methode einbauen und mit '/second' dekorieren

@app.route('/second')

def second():
  return 'Ein zweites Hallo'

Diese Methode wird dann beim URL http://<hostname>:8085/second angestoßen. Im Browser erscheint dann genau der String, den second() respektive index() zurückgeben.

Rückgabe von second() im Browser-Fenster
Rückgabe von second() im Browser-Fenster

Meistens heißt dieses Programm app.py oder run.py. Ich habe es im Repository jetzt aber first.py genannt.Gestartet wird es einfach mit

python first.py

Nach dem Start meldet sich Flask so:

Screenshot: Flask Anwendung wurde gestartet
Flask Anwendung wurde gestartet

Projekt einrichten

Eine komplexere Flask-Anwendung benötigt verschiedene Verzeichnisse, die richten wir jetzt ein. Zunächst benötigen wir ein Projektverzeichnis und wechseln dort hinein.

mkdir renderhtml
cd renderhtml

Komplexe Web-Anwendungen bestehen aus HTML-Seiten, Bildern und Stylesheets, die bei Flask in verschiedenen Verzeichnissen abgelegt werden.

mkdir templates
mkdir -p static/css

In templates speichern wir die HTML Dateien, unter static landen alle statischen Ressourcen. Speziell die Stylesheet Dateien haben ein eigenes Unterverzeichnis css.

HTML Seite rendern

Wir wollen natürlich nicht nur irgendwelche Strings aus unserer Webanwendung zurückgeben sondern komplexere Seiten bauen, die Ergebnisse aus Python präsentieren können.

Lege dazu den folgen HTML Code unter templates/index.html ab.

<!DOCTYPE html>

<html lang='en'>
<head>
  <meta charset='utf-8' />
  <title>Title von templates/index.html</title>
</head>

<body>
 <p>
   Hier steht der <strong>Text der Seite <em>{{counter}}</em></strong>
  </p>
</body>
</html>

Dies ist eine einfache HTML Seite mit Ausnahme des Konstrukts {{counter}}. Alles, was zwischen zwei geschwungenen Klammern steht, versucht das Flask-Framework als Variable zu interpretieren und den Wert der Variable einzusetzen.

Jetzt brauchen wir noch unsere Web-App. Wie oben gesehen hat sie eine index() Methode die für den Basis-URL dekoriert ist. Diesmal gibt die Methode keinen String zurück sondern über die render_template() Methode des Framework die index.html Seite.

from flask import Flask,render_template


app = Flask(__name__)
zaehler = 0
@app.route('/')

def index():
  global zaehler 
  zaehler=zaehler +1
  return render_template('index.html', counter=zaehler)

if __name__ == '__main__':
  app.run(host='0.0.0.0',port=8085, debug=True)

Die Zeile global zaehler ist notwendig, da für das Framework die globale Variable Zähler nicht ohne weiteres sichtbar ist. Deshalb müssen wir zaehler entsprechend deklarieren. Die Zeile render_template('index.html', counter=zaehler) liefert die HTML Seite aus und übergibt den Inhalt von zaehler unter dem Variablennamen counter an die Seite. Oben siehst du, wie du sie dann benutzen kannst.

Pythoncode in HTML

In der HTML-Seite kannst du nicht nur Variablen einsetzen lassen sondern auch Pythoncode ausführen lassen. Im Folgenden wollen wir eine Liste von Schülern an die Webseite übergeben und im HTML darüber iterieren, um sie einzeln in einer Liste auszugeben. Hier zunächst die Datei templates/students.html

<!DOCTYPE html>

<html lang='de'>
<head>
  <meta charset='utf-8' />
  <title>Schüler</title>
</head>

<body>
 <p>
   Schülerverzeichnis
  </p>
 <ul>
 {% for s in schueler %}
  {%if s['name'] == "Simpson" %}
  <li><b>{{s['name']}}, {{s['vorname']}}</b></li>
  {%else %}
  <li>{{s['name']}}, {{s['vorname']}}</li>
  {%endif %}
 {%endfor %}
</ul>
</body>
</html>

Du bemerkst hier, dass der Pythoncode zwischen {% %} Blöcken steht.

  • {% for %} ist die for-Schleife, die Notation ist weitgehend wie in Python, allerdings ohne den Doppelpunkt am Ende. Die Schleife muss durch {%endfor %} abgeschlossen werden. Alles, was zwischen for und endfor steht, wird so oft wiederholt, wie Elemente in der Liste schueler sind.
  • <%if %> kannst du für konditionale Blöcke benutzen. Hier werden alle Schüler mit Nachnamen ‚Simpson‘ fett gedruckt. Auch hier gilt: Die Bedingung des if wird wie in Python nur ohne Doppelpunkt am Ende notiert. Mit <%else> wird ein Block mit der gegenteiligen Bedingung eingeleitet <%endif%> beendet das if-Konstrukt.

Als nächstes erweitern wir das obenstehende Pythonprogramm um eine neue Methode, die die students.html aufruft und mit Daten versorgt.

schueler = [
    {'name':'Simpson','vorname': 'Bart'},
    {'name':'Simpson','vorname':'Lisa'},
    {'name':'van Houten','vorname':'Milhouse'},
    {'name':'Wiggum','vorname':'Ralph'},
    {'name':'Jones','vorname':'Jimbo'}
]

@app.route('/students')
def students():
  return render_template('students.html',schueler=schueler)

schueler ist eine Liste von Dictionaries jeder Eintrag besteht aus Namen und Vornamen. Theoretisch kann eine solche List auch von der Datenbank geliefert werden. Die Methode students() liefert unsere students.html Datei und übergibt die Schülerliste an sie. Die Methode wird mit http://<hostname>:8085/students aufgerufen. Wenn alles korrekt abläuft, erscheint im Browser dies hier

Liste der Schüler. Die Einträge mit Nachnamen Simpson sind fettgedruckt.
Liste der Schüler. Die Einträge mit Nachnamen Simpson sind fettgedruckt.

Formulare

Viele Webanwendungen (vielleicht sogar alle) erwarten vom Benutzer Eingabedaten, um ihre Berechnung durchzuführen. Es ist also Zeit für den Fibonacci Rechner. Wir legen ein neues Projektverzeichnis an

mkdir -p fib/static/css
mkdir fib/templates

Grundlage ist der Fibonacci-Generator. Zunächst die templates/index.html

<!DOCTYPE html>

<html lang='en'>
<head>
  <meta charset='utf-8' />
  <link href='static/css/skeleton.css' rel='stylesheet' type='text/css' />
  <title>Fibonacci Zahlen berechnen</title>
</head>

<body>
 <h2>Fibonacci Generator </h2
 <!--FORM -->
 <form action='fib' method='post'>
    <label> Folgen Element</label>
    <input 
       type='text'
       placeholder='Fibonacci Element'
       name='element'
       value='{{request.form.element}}'
    </input><br />
    <button type='submit'>Berechnen</button>
    <p>Formel: {{formel}} </p>
    <p>Fibonacci-Zahl: {{result}} </p>
 </form>
</body>
</html>

Die Seite definiert eine einfache Eingabemaske mit einem Textfeld für das Folgenelement und einem Submit-Button. Beachte, dass die <form> den Typ ‚post‚ und als action 'fib‘ hat. Das Textfeld übergibt den eingegeben Wert mit {{request.form.element}} an den Request, dort kann unsere Pythonmethode sich den Wert abholen. Außerdem wollen wir dem User zeigen, aus welchen beiden Werten sich das Fibonacci-Element berechnet hat. Dazu werden die beiden Vorgängerelemente der formel hinzugefügt und über render_template() an die index.html gesendet. Du siehst hier auch, wie du mehrere Variablen an eine Seite senden kannst.


from flask import Flask,render_template,request
from fib_gen import fib_generator
import logging

logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
app = Flask(__name__)

@app.route('/')
def index():
  return render_template('index.html')

@app.route('/fib',methods=['GET','POST'])
def fib():
  fibg = fib_generator()
  result = ''
  logging.debug(f'request.method={request.method}')
  if request.method == 'POST':
     element = request.form['element']
     
     logging.debug(f'berechne Element:{element}')

     n= int(element)

     formel = '' # Berechnungsformel initialisieren.
     if element != None:
       for i in range(n+1):
         fib = next(fibg)
         if i == n-2: # fib(n-2) zur Berechnungsformel dazu

           formel += str(fib)
         if i == n-1: # fib(n-1) mit + Zeichen zur Berechnungsformel dazu
           formel += '+' + str(fib)
         
       logging.debug(f'Fibonacci-Zahl: {fib}')
       logging.debug(f'formel={formel}')
       result=str(fib)
  elif request.method == 'GET':
    logging.debug('GET-Request')
  return render_template('index.html', result=result,formel=formel)

if __name__ == '__main__':
  app.run(host='0.0.0.0',port=8085, debug=True)

Das ganze sieht dann so aus:

Damit beschließe ich diesen Teil es Kurses.Du findest den Sourcecode dieses Teil im Git-Repository. Im nächsten Teil trennen wir die Entwicklungsumgebungen verschieden Python Projekte mit Hilfe von virtuellen Umgebungen besser voneinander.

Cookie Consent Banner von Real Cookie Banner