Das Template-System von Flask

Flask hat ein sehr flexibles und stabiles Konstrukt eingebaut, mit dem sich HTML-Ansichten aus Einzelteilen zusammensetzen lassen. Jinja2 heißt es und arbeitet mit dem Begriff Template. Ein Template ist ein Stück HTML, das mit anderen Stücken kombiniert werden kann. Dabei gibt es einige praktische Konzepte, die die Arbeit noch erleichtern:

  • Templates können durch andere Templates erweitert werden (extend).
  • Templates können Platzhalter enthalten, die dynamische mit Werten aus den Route-Funktionen gefüllt werden können.
  • Jinja2 stattet Templates mit Kontrollstrukturen aus - was HTML nicht kann -, sodass Schleifen und Verzweigungen möglich sind.

Eine detaillierte Dokumentation von Jinja2 findet sich auf der Homepage des Projekts.

Umbau des Secondhandblumenladens

Bisher liefern wir ganze HTML-Dokumente als Templates aus.

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

Wir stellen aber fest, dass diese Dokumente zu großen Teilen identisch sind, sich aber an einigen Stellen unterscheiden. Diese Stellen gilt es zu identifizieren.

Aus der Datei index.html machen wir daher durch Kopieren die Datei layout.html und ersetzen in der Kopie den inhaltlichen Teil durch einen Block:

<!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="/">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>
        {% block content %}{% endblock content %}
        <div class="clearer"></div>
    </div>
</div>
</body>
</html>

An der Stelle, wo wir den Block definiert haben, soll in Zukunft immer nur der Teil "injiziert" werden, der für die entsprechende Seite gültig ist. Um ein Beispiel zu geben, bauen wir daher die Seite index.html um:

{% extends "layout.html" %}
{% block content %}
    <h2>Herzlich Willkommen!</h2>
    <img class="align-left" src="../static/img/withered_flowers.jpg" alt="As Beauty Withers by bogenfreund@flickr.com"
         title="As Beauty Withers by bogenfreund@flickr.com"/>

    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum
        sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
{% endblock %}

In der ersten Zeile sagen wir, dass dieses Template das Template layout.html erweitert. Und an die Stelle, wo wir in der layout.html den Block content vorgesehen haben, wird der Teil eingefügt, der hier zwischen den statement tags für den Block content steht. Flask baut dann beide Teile zusammen und liefert ein komplettes Dokument aus. In der app.py brauchen wir nichts mehr zu ändern.

Werte ans Template übergeben

Spannend wird es nun, wenn wir Werte aus den Route-Funktionen an die Templates übergeben. Denn dann können wir mit Python Daten berechnen, aus einer Datenbank holen, von Sensoren einlesen etc. und dynamische Webseiten generieren!

Mit einem einfachen Beispiel wollen wir uns dieses Potenzial erschließen. In der app.py übergeben wir den Namen der Ansicht an das Templates, um es dort anschließend dynamisch einzubauen:

@app.route('/')
def index():
    return render_template('index.html', title='Home')

title ist hierbei der Name einer Variablen, die wir in den Templates zur Verfügung haben. Daher können wir unsere layout.html im <head> entsprechend modifizieren.

<head>
    <title>{{ title }} | Secondhandblumen Petersen in Hamburg</title>
    <meta charset="UTF-8"/>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"/>
</head>

Aufgaben und Fragestellungen

  1. Bauen Sie die gesamte Website nach diesem Ansatz um!
  2. Überlegen Sie, wie man eine Bildergalerie aus einem Ordner voller Bilder bauen könnte!
  3. Überlegen Sie, wie man eine Tabelle mit Produkten und Preisen aus einer Python-List oder einem Dictionary generieren kann!
  4. Bauen Sie Ihr Webseiten-Projekt so um, dass es mit dem Template-System von Flask läuft!
  5. Gegeben ist eine Python-List in der Form tiere = ['Hund','Katze','Maus','Igel','Giraffe']. Übergeben Sie diese Liste aus einer Routen-Funktion an ein Template und erstellen Sie daraus eine ungeordnete HTML-Liste (<ul><li></li></ul>)!