Caching

Caching bedeutet, dass Ergebnisse von Berechnungen oder Datenbankabfragen zwischengespeichert werden, um sie bei späteren Anfragen schneller wieder bereitstellen zu können. Statt eine teure Operation erneut auszuführen, wird das bereits berechnete Ergebnis aus dem Cache zurückgegeben.

Warum Caching?

Typische Gründe für den Einsatz von Caching:

  • Reduzierung von Datenbankabfragen

  • schnellere Antwortzeiten

  • geringere Serverlast

  • bessere Skalierbarkeit

Caching ist besonders sinnvoll bei:

  • häufig abgefragten Daten

  • teuren Berechnungen

  • Inhalten, die sich selten ändern

Caching-Ebenen in Django

Django bietet mehrere Möglichkeiten, Caching einzusetzen – je nach gewünschter Granularität.

Gesamte View cachen

Die einfachste Variante ist das Caching kompletter Views.

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):
    ...

Vorteile:

  • sehr einfach

  • große Performance-Gewinne

Nachteile:

  • wenig flexibel

  • ungeeignet für dynamische Inhalte (z. B. pro User)

Template-Fragmente cachen

Hier werden nur Teile eines Templates gecached.

{% load cache %}
{% cache 300 sidebar %}
    ... teure Sidebar ...
{% endcache %}

Vorteile:

  • feingranular

  • gut für teilweise dynamische Seiten

Nachteile:

  • etwas komplexer

  • mehr Verantwortung im Template

Auch kontextabhängig möglich:

{% cache 300 sidebar request.user.username %}
    ... user-spezifischer Inhalt ...
{% endcache %}

Low-Level Cache API

Für maximale Kontrolle kann direkt auf den Cache zugegriffen werden.

from django.core.cache import cache

cache.set("my_key", "value", 60)
value = cache.get("my_key")

Vorteile:

  • maximale Flexibilität

  • ideal für komplexe Logik

Nachteile:

  • mehr Code

  • Fehleranfälliger (z. B. Cache-Invaliderung)

Caching Backends

Django unterstützt verschiedene Backends:

  • Local Memory (nur für Entwicklung)

  • Dateisystem

  • Datenbank

  • Memcached

  • Redis

Beispiel (einfacher Dev-Cache):

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "unique",
    }
}

Für produktive Systeme werden meist externe Systeme genutzt:

  • Redis

  • Memcached

Diese sind:

  • schneller

  • skalierbar

  • unabhängig vom Django-Prozess

Bemerkung

Redis ist heute die am häufigsten verwendete Lösung im Django-Umfeld.

Wann lohnt sich Caching?

Caching ist nicht immer sinnvoll.

Gut geeignet:

  • Listenansichten

  • Dashboards

  • teure Queries

Weniger geeignet:

  • stark personalisierte Inhalte

  • häufig wechselnde Daten

Wichtig ist auch die Cache-Invalidierung: Wann werden Daten aktualisiert oder gelöscht?

Caching in der Praxis

In realen Projekten wird Caching gezielt und selektiv eingesetzt. Ziel ist nicht, „alles zu cachen“, sondern die größten Performance-Gewinne mit möglichst wenig Komplexität zu erreichen.

Typische Kandidaten für Caching

Diese Dinge werden in der Praxis häufig gecached:

  • Listenansichten (z. B. Event-Listen)

  • Startseiten

  • Aggregationen (Counts, Statistiken)

  • Navigationselemente (Kategorien, Menüs)

  • externe API-Responses

Beispiel:

@cache_page(60 * 5)
def event_list(request):
    ...

Oder gezielt im Code:

def get_top_categories():
    key = "top_categories"
    data = cache.get(key)

    if data is None:
        data = Category.objects.annotate(...).order_by(...)[:5]
        cache.set(key, data, 300)

    return data

Was man eher nicht cachen sollte

  • stark personalisierte Inhalte (pro User)

  • Formulare / POST-Requests

  • sehr kurzlebige Daten

  • sicherheitskritische Inhalte

Faustregel: Je dynamischer die Daten, desto schwieriger wird Caching.

Cache-Invalidierung (wichtig!)

Das größte Problem beim Caching ist nicht das Speichern, sondern das Invalidieren.

Typische Strategien:

Zeitbasiert (einfach):

  • Cache läuft nach X Sekunden ab

cache.set("key", value, 300)

Event-basiert (genauer):

  • Cache wird aktiv gelöscht

cache.delete("top_categories")
    1. nach einem Save:

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)
    cache.delete("top_categories")

Typische Fehler

  • zu viel cachen → schwer wartbar

  • kein Ablaufdatum setzen

  • Cache vergessen zu invalidieren

  • QuerySets ungefiltert cachen

Wichtig: Caching ist eine Optimierung, kein Ersatz für saubere Queries.

Einfache Strategie für den Einstieg

Für die meisten Projekte reicht:

  1. View-Caching für einfache Seiten

  2. gezieltes Low-Level-Caching für teure Queries

  3. Redis als Backend

Das deckt bereits 80–90 % aller Anwendungsfälle ab.

Good practice

Starte ohne Caching und optimiere erst bei Bedarf. Miss die Performance und cache gezielt die Stellen, die wirklich teuer sind.

Zusammenfassung

Caching ist ein zentrales Werkzeug zur Performance-Optimierung. Django bietet dafür mehrere Ebenen – von einfachen View-Caches bis hin zur Low-Level-API. Für den Einstieg reicht meist View- oder Template-Caching, während komplexere Szenarien gezieltere Strategien erfordern.