Aus statisch mach dynamisch

Der folgende Abschnitt hat das Ziel, den Mehrwert dynamischer Webseiten herauszusarbeiten. Im vorangegangenen Beispiel wurde schon deutlich, dass übermittelte Parameter den "Bau" der Website, die an den Browser ausgeliefert wird, beeinflussen können.

Im folgenden Abschnitt werden wir die Ausgangsseite "Secondhandblumen Petersen" zu einer dynamischen Website umbauen.

Vorbereitung

Projektstruktur auf dem RPI anlegen

Wir werden zunächst eine neue Struktur für diesen Arbeitsschritt auf dem Raspberry vorbereiten.

/home/pi/www/secondhandblumen_flask/
├── app.py
└── 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 RPI kopieren

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

pi@raspberrypi:~/www/secondhandblumen_flask/templates $ cd
pi@raspberrypi:~ $ cd www/secondhandblumen_flask/templates/
pi@raspberrypi:~/www/secondhandblumen_flask/templates $ git clone https://xldrkp@collaborating.tuhh.de/itbh/secondhandblumen.git .

Wichtig ist der Punkt am Ende, denn er sagt, dass die Dateien direkt in dem Verzeichnis abgelegt werden, in dem wir uns befinden.

Die Datei app.py aufbauen

Bei Flask heißt der Vorgang, HTML-Seiten dynamisch zusammen zu bauen rendern. Daher importieren wir am Anfang unserer Hauptdatei auch ein neues Modul.

#!/usr/bin/env python3

from flask import Flask
from flask import request, render_template

app = Flask(__name__)

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

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

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

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

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

Zwischenstand checken

An dieser Stelle starten wir mal den Server, um uns das bisherige Ergebnis im Browser anzusehen.

pi@raspberrypi:~/www/secondhandblumen_flask $ python3 app.py

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

CSS und Bilder fehlen!
Abbildung 1: CSS und Bilder fehlen!

Woran liegt's?

Offensichtlich kann unsere derzeitige Anwendung noch nicht das CSS sowie die Bilder anzeigen. Gehen wir der Sache auf den Grund.

404 für Bilder und CSS
Abbildung 2: 404 für Bilder und CSS

Ein Blick in die Entwicklertools von Chromium zeigen, dass die Dateien style.css und das Bild 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.

pi@raspberrypi:~/www/secondhandblumen_flask $ tree
.
├── app.py
├── static
│   ├── css
│   └── img
└── templates
    ├── angebot.html
    ├── img
    │   ├── background_.jpg
    │   ├── man.jpg
    │   ├── photocredits.txt
    │   ├── stormtrooper.jpg
    │   └── withered_flowers.jpg
    ├── impressum.html
    ├── index.html
    ├── kontakt.html
    ├── LICENSE
    ├── style.css
    └── team.html

5 directories, 13 files

Nun verschieben wir die entsprechenden Dateien aus templates an die richtigen Stellen.

CSS-Datei verschieben

pi@raspberrypi:~/www/secondhandblumen_flask $ mv templates/style.css static/css/

Bilder verschieben

pi@raspberrypi:~/www/secondhandblumen_flask $ mv templates/img/* static/img/

Anschließend sieht unser Dateibaum wie folgt aus:

pi@raspberrypi:~/www/secondhandblumen_flask $ tree
.
├── app.py
├── static
│   ├── css
│   │   └── style.css
│   └── img
│       ├── background_.jpg
│       ├── man.jpg
│       ├── photocredits.txt
│       ├── stormtrooper.jpg
│       └── withered_flowers.jpg
└── templates
    ├── angebot.html
    ├── img
    ├── impressum.html
    ├── index.html
    ├── kontakt.html
    ├── LICENSE
    └── team.html

5 directories, 13 files

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 wir jetzt zwei Änderungen vor.

<!doctype html>
<html lang="de">
<head>
    <title>Home | Secondhandblumen Petersen in Hamburg</title>
    <meta charset="UTF-8"/>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"/>
</head>
<body>
<h1><a href="index.html">Secondhandblumen Petersen</a></h1>

<div id="wrapper">
    <div id="container">
        <div id="navcontainer">
            <ul>
                <li><a href="index.html">Home</a></li>
                <li><a href="angebot.html">Angebot</a></li>
                <li><a href="team.html">Team</a></li>
                <li><a href="kontakt.html">Kontakt</a></li>
                <li><a href="impressum.html">Impressum</a></li>
            </ul>
        </div>
        <h2>Herzlich Willkommen!</h2>
        <img class="align-left" src="{{ url_for('static', filename='img/withered_flowers.jpg') }}" alt="As Beauty Withers by bogenfreund@flickr.com"
             title="As Beauty Withers by bogenfreund@flickr.com"/>

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

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

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

Das gleiche tun wir für das Bild in der Datei index.html.

<img class="align-left" src="{{ url_for('static', filename='img/withered_flowers.jpg') }}" alt="As Beauty Withers by bogenfreund@flickr.com"
             title="As Beauty Withers by bogenfreund@flickr.com"/>

Erneut das Ergebnis betrachten

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

Homepage mit CSS und Bild
Abbildung 3: Homepage mit CSS und Bild

Wie geht's weiter?

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

Was passiert, wenn wir in der jetztigen Website navigieren?

Das funktioniert noch nicht. Was allerdings funktioniert - jedenfalls ein bisschen - ist die manuelle Eingabe der URLs im Browser: http://134.28.125.132:5000/team zeigt die Team-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?