Aus statisch mach dynamisch

Der folgende Abschnitt hat das Ziel, einige Vorteile dynamischer Webseiten herauszusarbeiten.

Vorbereitung

Projektstruktur anlegen

Legen Sie zunächst eine grundsätzliche Struktur für das Projekt an. In den folgenden Schritten erfolgt dies exemplarisch auf einem Raspberry Pi.

1/home/pi/www/flask-website/
2├── app.py
3└── templates/

Die Datei app.py kann mit touch app.py angelegt werden, der Ordner mit mkdir templates. Er dient dazu, die HTML-“Bauteile” aufzunehmen, aus denen wir im Folgenden dynamisch unsere Website zusammenbauen.

Statische HTML-Dokumente auf den Raspberry kopieren

Zunächst brauchen wir die HTML-Dokumente aus dem GitLab-Repository https://collaborating.tuhh.de/itbh/oer/informatik/codebeispiele/blumenladen.git. Sie können direkt mit git clone in den Ordner templates gezogen werden.

pi@raspberrypi:~ $ cd www/flask-website/
pi@raspberrypi:~/www/flask-website $ git clone https://collaborating.tuhh.de/itbh/oer/informatik/codebeispiele/blumenladen.git ./templates

Wenn Sie bisher noch nicht mit git gearbeitet haben: Das Kommando, das die nötigen Dateien aus dem Netz auf den Raspberry kopiert, lautet

git clone https://collaborating.tuhh.de/itbh/oer/informatik/codebeispiele/blumenladen.git ./templates

Die Dateistruktur sieht zu diesem Zeitpunkt aus wie folgt:

 1flask-website/
 2├── app.py
 3└── templates
 4    ├── datenschutz.html
 5    ├── img
 6    │   ├── blossom-plant-photography-flower-purple-petal-620190-pxhere-1500x450.jpg
 7    │   ├── favicon.png
 8    │   ├── logo_rose.png
 9    │   ├── nature-blossom-plant-flower-petal-bloom-795432-pxhere.com.jpg
10    │   ├── nature-blossom-plant-flower-petal-summer-1089950-pxhere.com.jpg
11    │   ├── roses-flowers-decoration-decorative-floral-decor-1418295-pxhere.com.jpg
12    │   └── screenshot-blumenladen.png
13    ├── impressum.html
14    ├── index.html
15    ├── kontakt.html
16    ├── LICENSE
17    ├── README.md
18    └── style.css

Die Datei app.py aufbauen

Bei Flask heißt der Vorgang, HTML-Seiten dynamisch zusammen zu bauen rendern. Daher importieren Sie am Anfang der app.py ein neues Modul.

Kopieren Sie den folgenden Code in die neue app.py!

 1#!/usr/bin/env python3
 2
 3from flask import Flask
 4from flask import request, render_template
 5
 6app = Flask(__name__)
 7
 8@app.route('/')
 9def index():
10    return render_template('index.html')
11
12@app.route('/kontakt')
13def kontakt():
14    return render_template('kontakt.html')
15
16@app.route('/impressum')
17def impressum():
18    return render_template('impressum.html')
19
20@app.route('/datenschutz')
21def datenschutz():
22    return render_template('datenschutz.html')
23
24if __name__ =='__main__':
25    app.run(host="0.0.0.0", debug=True)

In der zweiten Zeile kommt render_template dazu. Es erlaubt Ihnen, mit return eine Datei zurückzugeben, die das HTML enthält. So können Sie HTML und Programmcode sauber voneinander trennen.

Zwischenstand checken

An dieser Stelle starten Sie den Server, um das bisherige Ergebnis im Browser zu überprüfen.

pi@raspberrypi:~/www/flask-website $ export FLASK_APP=app.py
pi@raspberrypi:~/www/flask-website $ export FLASK_ENV=development
pi@raspberrypi:~/www/flask-website $ flask run --host=0.0.0.0

Ein Aufruf der Seite im Browser mit http://[IP-Adresse des Pi]:5000/ zeigt folgende Ansicht:

Woran liegt’s?

Offensichtlich kann die derzeitige Anwendung noch nicht das CSS und die Bilder anzeigen. Gehen Sie der Sache auf den Grund. Das gelingt mit den mächtigen Chrome Developer Tools, die in Chrome/Chromium auf jeder Webseite eingeschaltet werden können. Auch andere Browser verfügen über solche Entwicklungswerkzeuge, allerdings gilt der Chrome/Chromium-Browser als Industriestandard unter Webentwickler:innen. Der Grund dafür liegt darin, dass der Browser von Google herausgebracht wird und Google sehr einflussreich geworden ist, was die Implementierung neuer Webstandards und -funktionen angeht.

In einem Video zeige ich die Grundlagen der Chrome Developer Tools und Möglichkeiten, den Datenverkehr zwischen Client und Server zu analysieren.

Video: Grundlagen der Chrome Developer Tools

Nachdem Sie das Video angeschaut haben, werden Sie die Fehlermeldung in der folgenden Abbildung sicherlich deuten können:

404 für Bilder und CSS

Ein Blick in die Entwicklertools von Chromium zeigt, dass die Dateien style.css und die Bilder aus img/ nicht geladen werden können: Der Server findet sie dort nicht.

Das Problem ist erklärbar, wenn man weiß, dass man für Flask statische Dateien woanders ablegen muss.

Statische Dateien für Flask verfügbar machen

Dem Dateibaum unseres Projekts fügen wir noch den Ordner static hinzu und darin zwei weitere Ordner css und img.

 1flask-website/
 2├── app.py
 3├── static
 4│   ├── css
 5│   └── img
 6└── templates
 7    ├── datenschutz.html
 8    ├── img
 9    │   ├── blossom-plant-photography-flower-purple-petal-620190-pxhere-1500x450.jpg
10    │   ├── favicon.png
11    │   ├── logo_rose.png
12    │   ├── nature-blossom-plant-flower-petal-bloom-795432-pxhere.com.jpg
13    │   ├── nature-blossom-plant-flower-petal-summer-1089950-pxhere.com.jpg
14    │   ├── roses-flowers-decoration-decorative-floral-decor-1418295-pxhere.com.jpg
15    │   └── screenshot-blumenladen.png
16    ├── impressum.html
17    ├── index.html
18    ├── kontakt.html
19    ├── LICENSE
20    ├── README.md
21    └── style.css

Verschieben Sie nun die entsprechenden Dateien aus templates an die richtigen Stellen.

CSS-Datei verschieben

1pi@raspberrypi:~/www/flask-website $ mv templates/style.css static/css/

Bilder verschieben

1pi@raspberrypi:~/www/flask-website $ mv templates/img/* static/img/

Alten Bilderordner löschen

1pi@raspberrypi:~/www/flask-website $ rm -rf templates/img/

Anschließend sieht der Dateibaum aus wie folgt:

 1flask-website/
 2├── app.py
 3├── static
 4│   ├── css
 5│   │   └── style.css
 6│   └── img
 7│       ├── blossom-plant-photography-flower-purple-petal-620190-pxhere-1500x450.jpg
 8│       ├── favicon.png
 9│       ├── logo_rose.png
10│       ├── nature-blossom-plant-flower-petal-bloom-795432-pxhere.com.jpg
11│       ├── nature-blossom-plant-flower-petal-summer-1089950-pxhere.com.jpg
12│       ├── roses-flowers-decoration-decorative-floral-decor-1418295-pxhere.com.jpg
13│       └── screenshot-blumenladen.png
14└── templates
15    ├── datenschutz.html
16    ├── impressum.html
17    ├── index.html
18    ├── kontakt.html
19    ├── LICENSE
20    └── README.md

Pfadangaben für CSS und Bilder anpassen

Flask weiß, wo sich die statischen Dateien befinden. In den HTML-Dateien ist dies aber noch nicht bekannt. Daher nehmen Sie jetzt in der index.html zwei Änderungen vor.

 1<!DOCTYPE html>
 2<html lang="de">
 3
 4<head>
 5    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 6    <title>Blumenladen Rose</title>
 7    <link href="style.css" rel="stylesheet" type="text/css" media="screen" />
 8    <link rel="icon" type="image/png" href="img/favicon.png">
 9</head>
10
11<body>
12
13[Markup gekürzt]

In der Zeile, die das CSS einbindet, wird der Pfad auf eine neue und besondere Art angegeben.

1<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"/>

Die beiden geschweiften Klammern {{ }} sind ein Ausgabebefehl von Jinja2. Sie werden später noch sehr viel mehr damit anfangen. An dieser Stelle kontruieren Sie einen korrekten Pfad zur CSS-Datei, damit diese auch gefunden wird.

Tun Sie das gleiche für die Bilder in der Datei index.html.

10[Markup gekürzt]
11<body>
12    <header>
13        <div class="head">
14            <div class="logo">
15                <a href="index.html"><img src="{{ url_for('static', filename='img/withered_flowers.jpg') }}" alt="Logo Blumenladen Rose"> </a>
16            </div>
17[Markup gekürzt]

Erneut das Ergebnis betrachten

Bei gestartetem Server kann man nun erneut das Ergebnis im Browser betrachten.

Homepage mit CSS und Bild

Wie geht’s weiter?

Das Potenzial dieser doch recht aufwändigen Umbauaktion ist bei Weitem noch nicht ausgeschöpft. Außerdem haben Sie noch nicht alle Probleme gelöst.

Was passiert, wenn Sie in der jetztigen Website navigieren?

Das funktioniert noch nicht. Was allerdings funktioniert - jedenfalls ein bisschen - ist die manuelle Eingabe der URLs im Browser: http://localhost:5000/impressum zeigt die Impressum-Seite an, aber schon wieder ohne CSS und ohne Bilder.

Was muss man nun machen, damit wenigstens hier dass CSS sowie die Bilder korrekt angezeigt werden?

Zurück
Weiter