← Zurück zum Blog
WagtailPerformance2. Juni 2026· 13 min Lesezeit

Wagtail-Performance: StreamField & Seiten-Queries optimieren

Inhalt
  1. Das Query-Problem in Wagtail
  2. specific() richtig einsetzen
  3. StreamField-Rendering cachen
  4. Bilder & Renditions optimieren
  5. Navigation und Menüs cachen
  6. Template-Fragment-Caching
  7. Fazit

Ich werde häufig zu bestehenden Wagtail-Projekten geholt, die "langsam geworden" sind. In den meisten Fällen liegt es nicht an Wagtail, sondern an einer Handvoll typischer Muster. Hier zeige ich die Stellen, an denen ich zuerst schaue.

Das Query-Problem in Wagtail

Wagtails Seitenbaum ist mächtig, aber er verführt zu vielen Datenbankabfragen. Der Klassiker: eine Navigation oder Listenansicht, die pro Seite eine eigene Query auslöst.

# Ineffizient: N+1 beim Zugriff auf Kindseiten
for page in HomePage.objects.live():
    for child in page.get_children().live():  # je 1 Query pro Seite
        print(child.title)

Miss zuerst, bevor du optimierst. Die Wagtail-Debug-Toolbar (oder django-debug-toolbar) zeigt dir die Query-Zahl pro Seite:

pip install wagtail-debugtoolbar

# settings.py (nur Entwicklung)
INSTALLED_APPS += ["wagtail.contrib.styleguide", "debug_toolbar"]

specific() richtig einsetzen

Wagtail speichert Seiten in einer Basistabelle plus je einer Tabelle pro Seitentyp. Ein get_children() liefert Basis-Page-Objekte; der Zugriff auf typspezifische Felder löst dann Nachladen aus. .specific löst das gebündelt:

# Statt N Nachlade-Queries: eine gebündelte Abfrage
children = page.get_children().live().specific()

# In Templates: specific über das QuerySet, nicht pro Objekt
{% for child in page.get_children.live.specific %}
    {{ child.title }}
{% endfor %}
Faustregel: Immer wenn du im Template auf Felder eines konkreten Seitentyps zugreifst, brauchst du specific() — aber setze es auf das QuerySet, nicht in einer Schleife.

StreamField-Rendering cachen

StreamField ist flexibel, aber das Rendern vieler Blöcke kann teuer werden — besonders wenn Blöcke Datenbankzugriffe oder Bild-Renditions auslösen. Fragment-Caching pro Seite hilft:

{% load cache wagtailcore_tags %}

{% cache 3600 page_body page.id page.last_published_at %}
    {% for block in page.body %}
        {% include_block block %}
    {% endfor %}
{% endcache %}

Der Cache-Key enthält page.last_published_at — so wird der Cache bei jeder Neuveröffentlichung automatisch ungültig. Kein manuelles Invalidieren nötig.

Bilder & Renditions optimieren

Jede {% image %}-Tag-Variante erzeugt eine Rendition, die beim ersten Aufruf berechnet und gespeichert wird. Zwei Fallstricke:

# Renditions vorab erzeugen (z.B. im Deploy oder per Management Command)
from wagtail.images.models import Image

for img in Image.objects.all():
    img.get_rendition("width-800")
    img.get_rendition("fill-400x300")

# Moderne Formate ausliefern
{% image page.hero_image width-1200 format-webp %}

Die Hauptnavigation ist auf jeder Seite gleich, wird aber oft pro Request neu aus dem Seitenbaum berechnet. Ein einfacher Low-Level-Cache spart viele Queries:

from django.core.cache import cache

def get_main_menu():
    menu = cache.get("main_menu")
    if menu is None:
        root = Page.objects.get(slug="home")
        menu = list(root.get_children().live().in_menu().values("title", "url_path"))
        cache.set("main_menu", menu, 3600)
    return menu

# Cache bei Seitenänderung leeren (Signal):
from wagtail.signals import page_published
page_published.connect(lambda **kw: cache.delete("main_menu"))

Template-Fragment-Caching

Wagtail bringt mit {% wagtailpagecache %} (ab Wagtail 5) einen Baustein mit, der Seiten-Caching inklusive korrekter Invalidierung vereinfacht:

{% load wagtailcore_tags %}

{% wagtailpagecache 3600 "sidebar" %}
    {# teure Sidebar-Logik #}
{% endwagtailpagecache %}

Fazit

Die typische Reihenfolge bei einer langsamen Wagtail-Site: (1) Queries messen, (2) specific() auf QuerySets, (3) StreamField- und Menü-Caching, (4) Bild-Renditions vorab generieren. In den meisten Projekten bringt allein das den größten Sprung — ohne Infrastruktur-Änderung.

Yevhen Chubchyk
Yevhen Chubchyk
Senior Python / Django Entwickler · Freelancer seit 2016 · 20+ Jahre IT-Erfahrung. Wagtail-Projekte für Kunden im DACH-Raum.