Zum Inhalt

Flask

Flask ist ein Web-Framework, das die Entwicklung von Webanwendungen vereinfacht. Es verarbeitet HTTP-Anfragen (Requests) mit einem einfachen URL-Routing. Es nutzt die Template-Engine Jinja2 Kapitel

Homepage

Installation

pip install flask

Verzeichnis-Struktur

Eine Flask-App geht von einer standardisierten Verzeichnis-Struktur aus:

Info

/prj (1)
    app.py (2)
    mod1.py
    ./lib1 (3)
        ./__init__.py
        ./libfunc.py
    ./static (4)
        ./css
        ./img
        ./js    
    ./template (5)
        ./index.html.jinja
        ./page2/index.html.jinja
        ./page3/index.html.jinja
        ...
  1. Das Hauptverzeichnis der Anwendung.

  2. Der Python-Modul, in dem die Anwendung definiert wird.

  3. Ein Modul für eine Bibliothek, die von der Anwendung verwendet wird.

  4. Die Verzeichnisse static und template, die für das HTML-Rendering verwendet werden.

  5. Die Verzeichnisse css, img und js, die für das HTML-Rendering verwendet werden.

Erstellen einer Basis-Anwendung

hello-World-Anwendung

In einem ersten Schritt muss eine Instanz der Flask-Anwendung erstellt werden: app = Flask(__name__). Dann wird eine Route mit dem Namen / angelegt, die eine Funktion index() aufruft:

app0.py: Welcome
from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():
    return 'Hello, World'

if __name__ == '__main__':
    app.run(debug=True, port=8001, host="127.0.0.1")

Mit dem Befehl app.run(debug=True) wird die Anwendung im Debug-Modus gestartet, der den Server auf Port 8001 startet. Sobald ein Browser auf URL http://127.0.0.1:8001/ angefordert wird, wird der Endpoint index() aufgerufen und im Browser eine HTTP-Response mit dem Text "Hello, World" ausgegeben.

Terminal-Ausgabe
    P:\docs\_frameworks\_flask\py> p: && cd p:\docs\_frameworks\_flask\py && cmd /C "c:\py\Python312\python.exe "c:\Users\studi\.vscode\extensions\ms-python.debugpy-2025.6.0-win32-x64\bundled\libs\debugpy\launcher" 52320 -- P:\docs\_frameworks\_flask\py\app0.py "
    * Serving Flask app 'app0'
    * Debug mode: on
    WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
    * Running on http://127.0.0.1:8001
    Press CTRL+C to quit
    * Restarting with watchdog (windowsapi)
    * Debugger is active!
    * Debugger PIN: 965-944-617
    127.0.0.1 - - [09/Apr/2025 10:08:04] "GET / HTTP/1.1" 200 -

Rendering einer html-Seite

In der Regel möchte man beim Aufruf einer Url eine Webseite anzeigen. Das wird mit dem Befehl render_template() durchgeführt, dem das eine HTML-Seite mit dem Namen index.html.jinja aus dem Ordner _flask/templates/ verwendet wird.

app1.py, Rendering
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from flask import Flask
from flask import render_template

app = Flask(__name__)

@app.route('/')
def index():
    name = ['Rosalia','Otto']
    return render_template('index.html.jinja', title='Welcome', members=name)

if __name__ == '__main__':
    app.run(debug=True, port=8001, host="127.0.0.1")    

Die HTML-Seiten können in der Datei index.html.jinja angelegt werden.

index.html.jinja, Rendering
<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>{{ title }}</h1>
        <ul>
        {% for member in members: %}
        <li>{{ member }}</li>
    {% endfor %}
    </ul>
    </body>
</html>

Routing mehrerer Seiten (Endpoints)

Eine Website besteht i.d.R. aus mehreren Seiten. Die Routen bzw. Endpoints werden mit dem Decorator @app.route('/') definiert.

app.py, n Endpoints
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from flask import Flask
from flask import render_template

app = Flask(__name__)

@app.route('/')
def index():
    name = ['Rosalia','Otto']
    return render_template('index.html.jinja', title='Welcome', members=name)

@app.route('/ng2/')
def index2():
    name = 'Franz'
    return render_template('index2.html.jinja', title='Welcome', members=name)

@app.route('/ng3/')
def index3():
    name = ['Rosalia','Otto']
    return render_template('index3.html.jinja', title='Welcome', members=name)

if __name__ == '__main__':
    app.run(debug=True, port=8001, host="127.0.0.1")     

Für die Endpoints ng2 und ng3 werden responsive Webdesigns genutzt:

Responsive Webdesigns
    <!DOCTYPE html>
    <html lang="de">

    <head>
        <title>TransferFactory - LabTour</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>


    </head>

    <body>

        <div class="container p-5 my-5 bg-primary text-white text-center">
            <h1>IoT-Plattform {{members}}</h1>
            <p>Industrie 4.0 Demonstrationsanlage</p>

        </div>

        <div class="container pt-3">

                <div class="card">
                    <div class="card-header">
                            Dashboards
                    </div>
                        <div class="card-body">
                            <p>
                                <button type="button" class="btn btn-primary btn-block"
                                    onclick="self.location.href='http://192.168.178.81:3000/d/s51NWKEGk/iot-3-4-5?orgId=1&refresh=10s'">Grafana</button>
                                <button type="button" class="btn btn-primary btn-block"
                                    onclick="self.location.href='http://192.168.178.81:1880/ui'">node-RED</button>

                            </p>
                        </div>
                    </div>
                </div>
        </div>
        <div>
            <p></p>
        </div>

        <div class="jumbotron text-center" style="margin-bottom:0">
            <p>Fachhochschule Südwestfalen<br>
                &copy; 2020 Prof. Dr. Jürgen Bechtloff <a href="mailto:bechtloff.juergen@fh-swf.de"
                    style="font-size:20px">&#x2709;</a></p>
        </div>

    </body>

    </html>
    <!DOCTYPE html>
    <html lang="de">
    <meta charset="UTF-8">
    <title>{{ title }} </title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/5/w3.css">
    <style>
    </style>
    <script src=""></script>

    <body>
        <!-- Page content -->
        <div class="w3-content" style="max-width:2000px">

            <div class="w3-container w3-center w3-teal">
                <h1>IoT-Plattform</h1>
                <p>Industrie 4.0 Demonstrationsanlage</p>
            </div>

            <div class="w3-container w3-content w3-center w3-padding-64" style="max-width:800px" id="band">
                <p>j</p>
            </div>


            <div class="w3-card-4">
                <header class="w3-container w3-blue" onclick="Accord('c1')">
                    Dashboards
                </header>

                <div class="w3-container w3-hide" id="c1">
                    <p>
                        <button type="button" class="btn btn-primary btn-block" onclick="">Grafana</button>
                        <button type="button" class="btn btn-primary btn-block"
                            onclick="self.location.href=''">node-RED</button>

                    </p>
                </div>
            </div>
            <div class="w3-card-4">
                <header class="w3-container w3-blue"  onclick="Accord('c2')">

                    IoT-Clients
                </header>
                <div class="w3-container w3-hide" id="c2">
                    {% for s in members: %}
                    <li>{{ s }}</li>
                    {% endfor %}
                </div>
            </div>
        </div>

        </div>
        </div>
        <div>
            <p></p>
        </div>

        <!-- Footer -->
        <footer class="w3-container w3-center w3-opacity w3-light-grey">
            <p>Fachhochschule Südwestfalen<br>
                &copy; 2020 Prof. Dr. Jürgen Bechtloff <a href="mailto:bechtloff.juergen@fh-swf.de"
                    style="font-size:20px">&#x2709;</a></p>
        </footer>

    <script>
    function Accord(id) {
      var x = document.getElementById(id);
      if (x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
      } else { 
        x.className = x.className.replace(" w3-show", "");
      }
    }
    </script>
    </body>

    </html>

Zu dem Thema responsive Webdesign befasst sich Kapitel "Website"

Get and Post vom Browser

Wenn Daten zwischen Browser (Client) und Server (Flask-App) ausgetauscht werden sollen, dann werden die RestApi-Requests mit GET oder POST verbunden. Die Anfrage wird in der App als request gespeichert. Das ist ein Objekt, das den Request enthält. Es gibt verschiedene Möglichkeiten, wie man Daten aus dem Request extrahiert. Üblicherweise werden die Daten in Form eines HTML-Formulars übertragen.

Ein kleines Beispiel soll einen Login-Prozess illustrieren:

Login-Prozess
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    from flask import Flask
    from flask import render_template
    from flask import request

    app = Flask(__name__)


    @app.route('/')
    def index():
        return 'Hello, World'


    @app.route('/login', methods=['POST', 'GET'])
    def login():
        error = None
        if request.method == 'POST':
            if valid_login(request.form['username'],
                           request.form['password']):
                return log_the_user_in(request.form['username'])
            else:
                error = 'Invalid username/password'
        # the code below is executed if the request method
        # was GET or the credentials were invalid
        return render_template('login.html.jinja', title="Login", error=error)


    def valid_login(username, password):
        # check if the username/password combination is valid
        return True


    def log_the_user_in(username):
        print("Logging in user {0!r}".format(username))
        # do the actual login
        return "Logged in successfully"


    if __name__ == '__main__':
        app.run(debug=True, port=8001, host="127.0.0.1")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    <html>

    <head>
        <title>{{ title }}</title>
    </head>

    <body>
        <h1>{{ title }}</h1>

        <form action="" method="post">
            <p>Username<input type="text" name="username" value="{{ username }}"> {{ username }}</p>
            <p>Password<input type="password" name="password" value="{{ password }}"> {{ password }}</p>
            <br><input type="submit" value="Submit">
        </form>

    </body>

    </html>