Djangos Templates stehen zwei unterschiedliche Arten zur Verfügung, wie Variablen ins Template gelangen (Template-Filter und -Tags jetzt außen vorgelassen). Die lokalen Variablen, die pro View festgelegt werden und die Template-Context-Prozessoren (im folgenden TCP genannt), jeweils ein Dictionary mit Variablen, das allen Templates zur Verfügung steht.
Einige TCPs sind in der Grundkonfiguration eines Django-Projekts schon mit dabei und bestimmt hast du sie schon einmal gesehen:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
)
Hinweis: Wenn du ein neues Projekt mittels django-admin.py startproject foo erstellt hast, ist dieser Eintrag nicht in der settings.py vorhanden. Er steht aber in den Grundeinstellungen django.conf.global_settings. Wenn du etwas ändern willst, packe den oberen Schnipsel ans Ende deiner settings.py.
Diese Tupel wird in der Einstellung settings.TEMPLATE_CONTEXT_PROCESSORS festgelegt. Am bekanntesten wird wohl der media-TCP sein, er stellt allen Templates die Variable MEDIA_URL zur Verfügung, ein Link zum Ordner mit den statischen Mediendateien.
TCPs können natürlich auch selbst erstellt werden, die Syntax ist sehr einfach:
def mein_prozessor(request):
return {
'VARIABLEN_NAME': 'wert',
}
Es ist eine einfache Funktion die als einziges Argument die aktuelle request-Variable nimmt und ein Dictionary zurückgibt. Eingebunden wird sie in die settings.py wie oben schon beschrieben:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'mein_app.context_processors.mein_prozessor',
)
Es ist eine gute Idee, die Datei die diese Funktion beinhaltet, auch 'context_processors.py' zu nennen.
Nochmal im Vergleich
Da sich mit Quellcode eine Sache am besten verstehen lässt, hier noch einmal ein einfacher View:
def startseite(request):
return render_to_response(
'pfad/zum/template.html',
{'headline': 'Meine Startseite',
'text': 'Lorem ipsum dolor bla.'},
RequestContext(request)
)
Die hier benutzte render_to_response Funktion gibt das Template (erstes Argument) zurück mit den lokalen Variablen (zweites Argument) und stellt auch alle globalen TCPs bereit (drittes Argument). In einer flauschigen Grafik schaut das so aus:
Was nutzt man wann?
Wann man TCPs nutzt dürfte nun klar sein. Soll ein Wert jedem Template zur Verfügung stehen, baut man dafür einen TCP. Ein Beispiel ist auf dieser Seite meine Fußleiste, dort sind auf jeder Seite die neuesten Blogbeiträge und Bookmarks zu sehen.
Der FAQ-Teil
Nun bist du vielleicht auf diese Seite gelangt, weil man dich im Django-Channel hierher verwiesen hat. Jetzt kommen die häufigsten Fehler im Umgang mit Template-Context-Prozessoren (TCP).
Eine typisches Problem dürfte zum Beispiel sein:
Ich kann in meinem Template die
MEDIA_URLVariable nicht nutzen, sie gibt nur einen leeren String zurück.
Mögliche Fehlerquellen
1. Groß/Kleinschreibung
Ganz simpel eigentlich. In Django-Templates werden Variablen zwischen Groß- und Kleinschreibung unterschieden. Media_URL ist also nicht das selbe wie MEDIA_URL.
2. Du hast einen eigenen View geschrieben der render_to_response nutzt
Der häufigste Fehler ist, dass du render_to_response vergessen hast, als drittes Argument den Request-Context zur Verfügung zu stellen. Schau nochmal auf die Beispielfunktion von oben:
from django.template.context import RequestContext
def startseite(request):
return render_to_response(
'pfad/zum/template.html',
{'headline': 'Meine Startseite',
'text': 'Lorem ipsum dolor bla.'},
RequestContext(request)
)
RequestContext analysiert im Prinzip die Module aus settings.TEMPLATE_CONTEXT_PROCESSORS und stellt sie dem Template zur Verfügung.
Djangos Generic-Views machen das automatisch! Warum render_to_repsonse nicht? Im Prinzip geht es darum, dass du die Möglichkeit hast, diese Variablen nicht dem Template zur Verfügung zu stellen. Klingt komisch, ist aber so. Oft ist dies der Fall, wenn Dritte Zugriff auf die Templates haben und nicht alle globalen Variablen wissen sollen.
Das ist aber nicht DRY *kreisch*. Es gibt Mittel und Wege das semi-automatisch zu machen. Auf dieser Seite sind einige Shortcuts erklärt.
3. Du willst auf den request TCP zugreifen
Bis vor Django 1.0 war der TCP django.core.context_processors.request noch Teil der Grundeinstellungen. Dieser wurde nun (aus Sicherheits- oder Performancegründen, ich weiß es nicht) entfernt. Viele 3rd-Party-Apps nutzen diesen TCP ohne zu dokumentieren, wie er eingebunden wird.
Wenn du in deiner settings.py noch keine Definition für TEMPLATE_CONTEXT_PROCESSORS hast, packe diesen Schnipsel ans Ender der Datei:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.request',
)
Alternativ, wenn du schon eine Prozessoren-Liste hast, packe einfach django.core.context_processors.request dazu.
Das wars, eine erschöpfende Antwort auf die #1 FAQ im Django IRC-Channel. :-)
Comments closed
Sorry, new comments are no longer allowed for this entry.
Write me an email if you have feedback or any questions regarding this post. If you found this post useful and just want to say thank you then don't forget that I have an Amazon Wishlist. :-)