Flask-Template-Rendering

Das Verketten von HTML-Strings in Python-Code ist sowohl mühsam als auch gefährlich (anfällig für XSS-Schwachstellen). Flask integriert die Jinja2-Template-Engine, um dieses Problem zu lösen.

Vorlagen ermöglichen es Ihnen, Geschäftslogik von der Seitenpräsentation zu trennen und sicheren und wartbareren Code zu schreiben.


render_template-Grundlagen

render_template()Es ist die am häufigsten verwendete Template-Rendering-Funktion in Flask.

Der erste Parameter ist der Name der Template-Datei, und die folgenden Schlüsselwortargumente werden als Variablen an das Template übergeben.

Beispiel

# Dateipfad: app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
    # Template templates/index.html rendern, dabei die Variablen title und name übergeben
    return render_template("index.html", title=BEISPIEL Startseite, name="World")

@app.route("/user/<username>")
def profile(username):
    # Den Benutzernamen aus der URL an das Template übergeben
    return render_template("user.html", username=username, posts=[
        {"title": Flask-Einführung, "date": "2026-05-01"},
        {"title": Jinja2-Vorlage, "date": "2026-05-10"},
    ])

Template-Dateien werden im Projektverzeichnistemplates/Im Ordner abgelegt:

example-flask-test/
├── app.py
└── templates/
    ├── index.html
    └── user.html

Der Inhalt von index.html ist:

Beispiel (index.html)

<!-- Dateipfad: templates/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }} - BEISPIEL</title>
</head>
<body>
    <h1>{{ title }} </h1>
     <p>Hallo {{ name }}。</p>
</body>
</html>

Besuchen Siehttp://127.0.0.1:5000/, das Ausgabeergebnis ist:


Jinja2-Grundsyntax

Drei Kern-Syntaxen in Jinja2-Vorlagen:

Syntax Zweck Beispiel
{{ ... }} Variablenwerte ausgeben, HTML automatisch escapen {{ username }}
{% ... %} Kontrollanweisungen (if, for, block, usw.) {% if user %}
{# ... #} Kommentare, werden nicht im gerenderten Ergebnis angezeigt {# Dies ist ein Kommentar #}

Vorlagenbeispiel

Beispiel (user.html)

<!-- Dateipfad: templates/user.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ username }} - BEISPIEL</title>
</head>
<body>
    <h1>Persönliche Homepage von {{ username }}</h1>

    <!-- Bedingung: Wenn die posts-Liste leer ist, eine Hinweismeldung anzeigen -->
    {% if posts %}
        <h2>Neueste Artikel:</h2>
        <ul>
        <!-- Schleife über die posts-Liste -->
        {% for post in posts %}
            <!-- loop.index ist eine integrierte Jinja2-Variable, beginnend bei 1 -->
            <li>{{ loop.index }}. {{ post.title }} ({{ post.date }})</li>
        {% endfor %}
        </ul>
    {% else %}
        <p>Noch keine Artikel</p>
    {% endif %}

    <!-- Verwenden des Filters: upper wandelt Text in Großbuchstaben um -->
    <p>Benutzername in Großbuchstaben: {{ username|upper }}</p>
</body>
</html>

Gängige Filter

Filter werden verwendet, um das Ausgabeformat von Variablen mithilfe des Pipe-Symbols zu ändern.|Aufruf.

Filter Funktion Beispiel Ausgabe
upper In Großbuchstaben umwandeln {{ "hello"|upper }} HELLO
lower In Kleinbuchstaben umwandeln {{ "HELLO"|lower }} hallo
title Ersten Buchstaben groß schreiben {{ "hello world"|title }} Hello World
length Länge abrufen {{ [1,2,3]|length }} 3
default Standardwert festlegen {{ name|default("anonymous") }} Anonym (wenn name leer ist)
safe Als sicheres HTML markieren (kein Escaping) {{ "Fett"|safe }} Als fetter Text gerendert
join Liste zusammenfügen {{ ["a","b"]|join(",") }} a,b

Sicherheitswarnung:safeDer safe-Filter deaktiviert Auto-Escaping; verwenden Sie ihn nur, wenn Sie der Datenquelle absolut vertrauen. Verwenden Sie ihn niemals für Benutzereingaben.safe。


Auto-Escaping — XSS-Schutz

Jinja2 maskiert HTML standardmäßig bei allen Variablenausgaben; dies ist eine wichtige Verteidigung für die Websicherheit.

Wenn der vom Benutzer übermittelte Benutzername beispielsweise<script>alert("xss")</script>ist, wird er beim Rendern der Vorlage automatisch in sicheren Text umgewandelt:

<!-- 模板中直接使用变量 -->
<p>{{ username }}</p>

<!-- 渲染结果(HTML 特殊字符已被转义) -->
&lt;p&gt;&amp;lt;script&amp;gt;alert(&amp;quot;xss&amp;quot;)&amp;lt;/script&amp;gt;&lt;/p&gt;

Maskierung gilt für.html、.htm、.xml、.xhtml、.svgDie Vorlagendatei am Ende.


Template-Vererbung — doppelten Code vermeiden

Template-Vererbung ist eine der leistungsstärksten Funktionen von Jinja2. Sie ermöglicht es Ihnen, ein "Basislayout" zu definieren und dann Inhalte über untergeordnete Templates einzufügen.

Dadurch wird vermieden, dass gemeinsame Teile wie Header, Navigation, Fußzeilen usw. auf jeder Seite wiederholt geschrieben werden.

Basis-Template (übergeordnetes Template)

Beispiel

<!-- Dateipfad: templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{% block title %}BEISPIEL Flask-Tutorial{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <header>
        <h1>BEISPIEL Flask-Tutorial</h1>
        <nav>
            <a href="/">Startseite</a> |
            <a href="/about">Über uns</a>
        </nav>
    </header>

    <main>
    <!-- Block ist ein Platzhalterbereich, den untergeordnete Templates füllen oder überschreiben können -->
    {% block content %}{% endblock %}
    </main>

    <footer>
        <p>&copy; 2026 example.com</p>
    </footer>
</body>
</html>

Untergeordnetes Template (erbt von übergeordnetem Template)

Beispiel

<!-- Dateipfad: templates/index.html -->
{% extends "base.html" %}

<!-- Überschreibt den title-Block des übergeordneten Templates -->
{% block title %}EXAMPLE Tutorial - Startseite{% endblock %}

<!-- Füllt den content-Block des übergeordneten Templates -->
{% block content %}
    <h2>Willkommen bei EXAMPLE</h2>
    <p>{{ greeting }}</p>

    {% if user %}
        <p>Aktueller Benutzer: {{ user }}</p>
    {% else %}
        <p><a href="/login">Bitte melden Sie sich zuerst an</a></p>
    {% endif %}
{% endblock %}
Tags Funktion
{% extends "base.html" %} Deklarieren Sie, dass das aktuelle Template von base.html erbt (muss in der ersten Zeile stehen)
{% block name %}...{% endblock %} Definiere einen Block, der von untergeordneten Templates überschrieben werden kann
{{ super() }} Rufe den Inhalt des gleichnamigen Blocks des übergeordneten Templates innerhalb des Blocks des untergeordneten Templates auf.

Nach der Verwendung von Template-Vererbung müssen Sie nurbase.htmlan einer Stelle ändern, und die gemeinsamen Teile aller Seiten (wie Navigation, Footer) werden automatisch aktualisiert.


Eingebaute Objekte in Templates

Die folgenden Flask-Objekte können direkt in Templates verwendet werden, ohne dass sie überrender_template()übergeben werden:

Objekt Beschreibung Verwendungsbeispiel im Template
request Aktuelles Anfrageobjekt {{ request.path }}
session Aktuelle Sitzungsdaten {{ session.get("username") }}
g Globale Variablen auf Request-Ebene {{ g.user }}
config Anwendungskonfiguration {{ config["APP_NAME"] }}
url_for() URL-Generierungsfunktion {{ url_for("index") }}
get_flashed_messages() Flash-Nachrichten abrufen {% for msg in get_flashed_messages() %}...

Andere Templates einbinden — include

Verwendung{% include %}Du kannst ein anderes Template innerhalb eines Templates einbetten:

Beispiel

<!-- Dateipfad: templates/_navbar.html (Unterstrich-Präfix kennzeichnet ein partielles Template) -->
<nav style="background:#f0f0f0;padding:10px;">
    <a href="/">Startseite</a> |
    <a href="/posts">Artikel</a> |
    <a href="/about">Über uns</a>
</nav>

Beispiel

<!-- Navigationsleiste in jedes Template einbinden -->
<!DOCTYPE html>
<html>
<head><title>Seite</title></head>
<body>
    {% include "_navbar.html" %}

    <h1>Seiteninhalt</h1>
    <p>Dies ist der Hauptinhalt der Seite.</p>
</body>
</html>

Bewährte Praktiken: Template-Vererbung (extends) wird für die Wiederverwendung von Layouts auf Seitenebene verwendet,includeWird für die Wiederverwendung von Code auf Komponentenebene verwendet. Wiederverwendbare Komponenten wie Navigationsleisten und Seitenleisten eignen sich für include.


Vollständiges Beispiel: Blog-Startseite

Integrieren Sie das oben Gelernte in ein reales Szenario:

Beispiel

# Dateipfad: app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
    # Artikeldaten in der Datenbank simulieren.
    articles = [
        {"id": 1, "title": Flask-Einstiegsanleitung, "author": "example", "views": 1024},
        {"id": 2, "title": Jinja2-Templates erklärt, "author": "admin", "views": 512},
        {"id": 3, "title": RESTful-API-Design, "author": "example", "views": 256},
    ]
    return render_template("blog.html", articles=articles)

Beispiel

<!-- Dateipfad: templates/blog.html -->
{% extends "base.html" %}

{% block title %}Beispiel-Blog{% endblock %}

{% block content %}
    <h2>Neueste Artikel</h2>

    {% if articles %}
        {% for article in articles %}
            <!-- Unterschiedliche Stile je nach Aufrufzahl hinzufügen -->
            <div class="article" {% if article.views > 1000 %}style="background:#fff3cd;"{% endif %}>
                <h3>{{ article.title }}</h3>
                <p>Autor: {{ article.author }} | Aufrufe: {{ article.views }}</p>
                <!-- Verwende die loop-Variable, um ein Trennzeichen zu erstellen -->
                {% if not loop.last %}
                    <hr>
                {% endif %}
            </div>
        {% endfor %}
    {% else %}
        <p>Noch keine Artikel, bitte schau später wieder vorbei.</p>
    {% endif %}
{% endblock %}

Spezielle Jinja2-Variablen

Variable Beschreibung
loop.index Aktueller Schleifenindex, beginnt bei 1
loop.index0 Aktueller Schleifenindex, beginnt bei 0
loop.first Gibt an, ob es die erste Iteration der Schleife ist
loop.last Gibt an, ob es die letzte Iteration der Schleife ist
loop.length Gesamtlänge der Sequenz
Weitere Erweiterungen