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 - die HTML nicht hat -, sodass Schleifen, Verzweigungen und Datenmanipulationen möglich sind.

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

Umbau einer statischen Website

Bisher liefern Sie ganze HTML-Dokumente als Templates aus.

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

Wahrscheinlich haben Sie im Abschnitt Aus statisch mach dynamisch festgestellt, 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 Sie daher durch Kopieren die Datei layout.html und ersetzen in der Kopie den inhaltlichen Teil durch einen Block:

 1<!DOCTYPE html>
 2<html lang="de">
 3
 4<!-- Diese Datei ist die layout.html! Sie ist eine Kopie der index.html. -->
 5
 6<head>
 7    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 8    <title>Blumenladen Rose</title>
 9    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"/>
10    <link rel="icon" type="image/png" href="img/favicon.png">
11</head>
12
13<body>
14    <header>
15        <div class="head">
16            <div class="logo">
17                <a href="index.html"><img src="{{ url_for('static', filename='img/logo_rose.png') }}" alt="Logo Blumenladen Rose"> </a>
18            </div>
19            <nav class="navigation">
20                <ul>
21                    <li> <a href="index.html">Home</a></li>
22                    <li> <a href="#über">Über</a></li>
23                    <li> <a href="#galerie">Galerie</a></li>
24                    <li> <a href="#preise">Preise</a></li>
25                    <li> <a href="kontakt.html">Kontakt</a></li>
26                    <li> <a href="impressum.html">Impressum</a></li>
27                    <li> <a href="datenschutz.html">Datenschutz</a></li>
28                </ul>
29            </nav>
30        </div>
31    </header>
32
33    <div class="keyvisual">
34        <img src="{{ url_for('static', filename='img/blossom-plant-photography-flower-purple-petal-620190-pxhere-1500x450.jpg') }}" alt="Keyvisual mit Blumen" loading="lazy">
35    </div>
36
37    <main>
38        <h1>Blumenladen Rose</h1>
39        {% block content %}{% endblock content %}
40    </main>
41
42    <footer>
43        <div class="footer">
44            <div class="footercontainer">
45                <div>
46                    <h3>Kontakt</h3>
47                    <p>
48                        Blumenladen Rose <br>
49                        Maria Mustermann<br>
50                        Musterstraße 666<br>
51                        12345 Musterhausen
52                    </p>
53                </div>
54                <div>
55                    <h3>Öffnungszeiten</h3>
56                    <table class="oeffnungszeiten">
57                        <tr>
58                            <td>Montag</td>
59                            <td>08:00 - 16:30</td>
60                        </tr>
61                        <tr>
62                            <td>Dienstag</td>
63                            <td>08:00 - 16:30</td>
64                        </tr>
65                        <tr>
66                            <td>Mittwoch</td>
67                            <td>Geschlossen</td>
68                        </tr>
69                        <tr>
70                            <td>Donnerstag</td>
71                            <td>08:00 - 16:30</td>
72                        </tr>
73                        <tr>
74                            <td>Freitag</td>
75                            <td>08:00 - 15:00</td>
76                        </tr>
77                        <tr>
78                            <td>Samstag</td>
79                            <td>09:00 - 12:00</td>
80                        </tr>
81                        <tr>
82                            <td>Sonntag</td>
83                            <td>Geschlossen</td>
84                        </tr>
85                    </table>
86                </div>
87            </div>
88        </div>
89    </footer>
90</body>
91
92</html>

An der Stelle, wo Sie 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 Sie daher die Seite index.html um:

  1{% extends "layout.html" %}
  2{% block content %}
  3<div id="über">
  4    <h2>Über uns</h2>
  5    <div class="zweispaltig">
  6	<div>
  7	    <p>Ipsum enim ipsum dolore amet incididunt occaecat ipsum voluptate excepteur cillum. Aute quis
  8		quis commodo dolore mollit eiusmod dolore labore minim occaecat. Adipisicing velit aute dolore
  9		aute officia. Ea elit proident nulla exercitation non dolore nostrud et consectetur commodo
 10		minim.
 11		Non mollit aliqua voluptate esse reprehenderit consequat cupidatat. Consequat consequat ad in
 12		irure cupidatat laborum anim tempor deserunt. Cupidatat exercitation magna ea dolor id eiusmod
 13		ut qui consequat.</p>
 14	    <p>Tempor tempor non cillum laboris ullamco et magna labore est consectetur duis eiusmod aliquip.
 15		Irure ut consequat velit anim est sunt ex proident. Enim ad duis aute eiusmod velit dolore ut.
 16		Sint aute sint id incididunt exercitation est amet et. Laboris do mollit tempor consequat
 17		reprehenderit est consequat qui elit.
 18		Mollit ipsum non nulla officia non laborum aliquip laborum ullamco. Incididunt ad officia
 19		excepteur est Lorem id ex elit cillum do. Officia duis consequat fugiat tempor reprehenderit sit
 20		reprehenderit. Lorem irure aute enim exercitation.</p>
 21	</div>
 22    </div>
 23
 24</div>
 25
 26<div id="galerie">
 27    <h2>Galerie</h2>
 28    <div class="galerieliste">
 29	<figure>
 30	    <a href="#img1">
 31		<img src="img/nature-blossom-plant-flower-petal-bloom-795432-pxhere.com.jpg" class="thumbnail" loading="lazy">
 32	    </a>
 33	    <figcaption>Photo from <a href="https://pxhere.com/" target="_blank">Pxhere</a></figcaption>
 34	</figure>
 35
 36	<figure>
 37	    <a href="#img2">
 38		<img src="img/nature-blossom-plant-flower-petal-summer-1089950-pxhere.com.jpg" class="thumbnail" loading="lazy">
 39	    </a>
 40	    <figcaption>Photo from <a href="https://pxhere.com/" target="_blank">Pxhere</a></figcaption>
 41	</figure>
 42
 43	<figure>
 44	    <a href="#img3">
 45		<img src="img/roses-flowers-decoration-decorative-floral-decor-1418295-pxhere.com.jpg" class="thumbnail" loading="lazy">
 46	    </a>
 47	    <figcaption>Photo from <a href="https://pxhere.com/" target="_blank">Pxhere</a></figcaption>
 48	</figure>
 49
 50	<div>
 51	    <a href="#_" class="lightbox" id="img1">
 52		<img src="img/nature-blossom-plant-flower-petal-bloom-795432-pxhere.com.jpg" loading="lazy">
 53	    </a>
 54	    <a href="#_" class="lightbox" id="img2">
 55		<img src="img/nature-blossom-plant-flower-petal-summer-1089950-pxhere.com.jpg" loading="lazy">
 56	    </a>
 57	    <a href="#_" class="lightbox" id="img3">
 58		<img src="img/roses-flowers-decoration-decorative-floral-decor-1418295-pxhere.com.jpg" loading="lazy">
 59	    </a>
 60	</div>
 61
 62    </div>
 63</div>
 64
 65<div id="preise">
 66    <h2>Preise</h2>
 67    <div class="preise_grid">
 68	<div>
 69	    <table class="preise_table">
 70		<tr>
 71		    <th class="first-column">Name</th>
 72		    <th class="second-column">Farbe</th>
 73		    <th class="third-column">Preis</th>
 74		</tr>
 75		<tr>
 76		    <td>Rosen</td>
 77		    <td>rot</td>
 78		    <td>€ 1,99</td>
 79		</tr>
 80		<tr>
 81		    <td>Nelken</td>
 82		    <td>gelb</td>
 83		    <td>€ 0,89</td>
 84		</tr>
 85		<tr>
 86		    <td>Osterglocken</td>
 87		    <td>braun-gelb</td>
 88		    <td>€ 0,45</td>
 89		</tr>
 90		<tr>
 91		    <td>Tannenbäume</td>
 92		    <td>grün-braun</td>
 93		    <td>€ 9,99</td>
 94		</tr>
 95	    </table>
 96	</div>
 97	<div class="preise_text">
 98	    <p>Ipsum enim ipsum dolore amet incididunt occaecat ipsum voluptate excepteur cillum. Aute
 99		quis quis commodo dolore mollit eiusmod dolore labore minim occaecat. Adipisicing velit aute
100		dolore aute officia. Ea elit proident nulla exercitation non dolore nostrud et consectetur
101		commodo minim.
102		Non mollit aliqua voluptate esse reprehenderit consequat cupidatat. Consequat consequat ad
103		in irure cupidatat laborum anim tempor deserunt. Cupidatat exercitation magna ea dolor id
104		eiusmod ut qui consequat.</p>
105	</div>
106    </div>
107</div>
108{% endblock %}

In der ersten Zeile sagen Sie, dass dieses Template das Template layout.html erweitert. Und an der Stelle, wo Sie 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 Sie nichts mehr zu ändern.

Werte ans Template übergeben

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

Mit einem einfachen Beispiel erschließen Sie sich nun dieses Potenzial. In der app.py übergeben Sie den Namen der Seite an das Template, um ihn dort anschließend einzubauen:

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

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

 6<head>
 7    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 8    <title>{{ title }}</title>
 9    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"/>
10    <link rel="icon" type="image/png" href="img/favicon.png">
11</head>

Wenn alles klappt, sehen Sie nach dem Aktualisieren der Homepage im Tab des Browsers den Titel “Home”.

Aufgaben und Fragestellungen

  1. Bauen Sie die gesamte Beispielseite “Blumenladen” nach diesem Ansatz um!
  2. Bauen Sie Ihr Webseiten-Projekt so um, dass es mit dem Template-System von Flask läuft!
  3. Überlegen Sie: Welches Potenzial steckt in der Werteübergabe an Tempates? Welche Möglichkeiten ergeben sich für den Bau dynamischer Webseiten?
Zurück
Weiter