Jinja-Templates

Bei den von Flask verwendeten Jinja-Templates, handelt es sich um html-Dateien welche mit Template-Syntax erweitert wurden. Diese Syntax erlaubt das Definieren von Blöcken, sowie das Ersetzen von Platzhaltern für einzelne Element oder ganze Listen von Elementen.

Umgehen mit Listen und Dictionaries

Die Templates erhalten von der Flask-render-Methode benannte Argumente. Dabei kann es sich um einzelne Werte, Listen, Dictionaries oder Listen von Dictionaries handeln.

from flask import render_template

@app.route("/test-template")
def test_template():
    details = {"year": 2001, "seasons": 6, "description": "Ein Flugzeug stürzt auf einer einsamen Insel ab..."}
    actors = [{"id": 123, "name": "Evangeline Lilly", "rolle": "Kate Austen"}, {"id": 32, "name": "Jorge Garcia", "rolle": "Hugo Reyes"}]

    return render_template('test_template.html', title="Lost", details=details, actors=actors)

Die Template-Datei test_template.html gehört in den Unterordner templates. Neben «normalem» HTML-Code beinhaltet sie spezielle Template-Anweisungen:

  • {{ title }} wird ersetzt mit dem Inhalt des übergebenen Arguments title
  • {{ details.seasons }} wird ersetzt mit dem Eintrag seasons des Dictionary details

Alles zwischen {{ und }} ist ein Ausdruck der ins gerenderte Dokument ausgegeben wird.

Für die Liste actors brauchen wir eine for-Schleife. Diese wird mit {% for actor in actors %} eingeleitet und mit {% endfor %} beendet. Alles was dazwischen steht wird für jeden Listen-Eintrag actor der Liste ausgegeben. Da es sich bei den einzelnen Listen-Elemente wiederum um Dictionaries handelt, müssen wir auf die einzelnen Dictionary-Einträge zugreifen. Dies geschieht z.B. mit {{ actor.name }}.

{% und %} kennzeichnet einen Kontroll-Struktur-Ausdruck wie ein for oder ein if. Kontroll-Strukturen besitzen ein Start- und ein Endtag.

<html>
  <head>
    <title>{{ title }}</title>
    <link rel="stylesheet" type="text/css" href="static/style.css">
  </head>
  <body>
    <h1>{{ title }}</h1>
    <p>{{ details.description }}</p>
    <ul>
    {% for actor in actors %}
      <li>
        <a href="actor?id={{ actor.id }}"><strong>{{ actor.name }}</strong> als {{ actor.rolle }}</a>
      </li>
    {% endfor %}
    </ul>
    <p>Anzahl Seasons: {{ details.seasons }}<br>Startjahr: {{ details.year }}</p>
  </body>
</html>

Ruft man die oben definierte Route auf, so kombiniert Flask die bei render_template() ab dem zweiten Argument übergebenen Python-Variablen mit der im ersten Argument übergebenen Template-Datei. Wir erhalten den folgenden reinen HTML-Output welcher als Antwort an den Client geschickt wird:

<html>
  <head>
    <title>Lost</title>
    <link rel="stylesheet" type="text/css" href="static/style.css">
  </head>
  <body>
    <h1>Lost</h1>
    <p>Ein Flugzeug stürzt auf einer einsamen Insel ab...</p>
    <ul>
      <li>
        <a href="actor?id=123"><strong>Evangeline Lilly</strong> als Kate Austen</a>
      </li>
      <li>
        <a href="actor?id=32"><strong>Jorge Garcia</strong> als Hugo Reyes</a>
      </li>
    </ul>
    <p>Anzahl Seasons: 6<br>Startjahr: 2001</p>
  </body>
</html>

Definieren von Blöcken

Oft hat man mehrere Seiten für eine Webapp. Diese sollten alle ähnlich aussehen und besitzen deshalb auch über weite Strecken denselben HTML-Code. Mit den Jinja-Templates kann man ein «Basis»-Template definieren, vorauf dann andere Templates aufbauen können. So erspart man sich viel mehrfachen HTML-Code und kann Änderungen rasch und einheitlich umsetzen.

Wir definieren also ein Template base.html:

<html>
  <head>
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="static/style.css">
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

Unser «Basis»-Template enthält zwei Blöcke: title und content. Wenn wir nun in unserem Template test_template.html dieses «Basis»-Template als Grundlage verwenden, so müssen wir nur noch diese Blöcke definieren. Der Rest wird aus dem «Basis»-Template übernommen.

{% extends 'base.html' %}

{% block title %}{{ title }}{% endblock %}

{% block content %}
    <h1>{{ title }}</h1>
    <p>{{ details.description }}</p>
    <ul>
    {% for actor in actors %}
      <li>
        <a href="actor?id={{ actor.id }}"><strong>{{ actor.name }}</strong> als {{ actor.rolle }}</a>
      </li>
    {% endfor %}
    </ul>
    <p>Anzahl Seasons: {{ details.seasons }}<br>Startjahr: {{ details.year }}</p>
{% endblock %}

Zuerst wird mit {% extends 'base.html' %} angegeben, welches «Basis»-Template wir verwenden wollen. Anschliessend werden nur noch die zu überschreibenden Blöcke mit der Syntax {% bock name %} angeben.

Das Ergebnis der Renderfunktion ist genau gleich wie im Beispiel ohne «Basis»-Template.


Offizielles Tutorial
http://flask.pocoo.org/docs/1.0/tutorial/templates/