.. _context_processors: Context Processors ************************ Manchmal ist es notwendig, Werte aus der Datenbank auf allen Seiten der Website auszugeben, zum Beispiel der Name der Website. Konkret heisst das für uns, dass jede View zusätzlich noch ein weiteres Objekt im Kontext an das Template überreichen müsste. Das klingt ziemlich aufwändig. Natürlich könnte man den Wert auch hardkodiert in den Settings hinterlegen, nur wäre er dann nicht von Moderatoren oder anderen Staff-Membern editierbar. Bei einer Änderung an den Settings müsste das System neu deployed werden. Besser wäre es, wenn wir solche Aufgaben über die Administrationsoberfläche lösen könnten. Mit den Methoden, die wir bisher kennengelernt haben, ist das aufwändig. Was ist ein Context-Prozessor? ------------------------------- Mit Context-Prozessoren wird zusätzlicher Kontext an die Template-Engine übergeben, ohne ihn explizit in jeder View mit angeben zu müssen, was sehr müheslig wäre. Django besitzt schon ein paar ``built-in`` Context-Prozessoren, zum Beispiel das Übergeben der Success-Messages an eine View. Diese Kontext-Prozessoren sind in der ``settings.py`` in der ``TEMPLATES``-Konstante angelegt. Der Message-Kontextprozessor sieht zum Beispiel so aus: ``django.contrib.messages.context_processors.messages`` Eigene Context-Prozessoren entwickeln -------------------------------------- Wir können natürlich auch eigene Kontext-Prozessoren entwickeln und in den Settings hinterlegen. Wir wollen jetzt den Namen der Website über die Administrationsoberfläche verfügbar machen und über einen Kontext-Prozessor auf jeder View ausgeben. Es bietet sich also an, für System-Settings ein eigenes Modell anzulegen, das später über die Administrationsoberfläche editiert werden kann. Django Site Framework ------------------------ Django wird mit dem sogenannten Sites-Framework ausgeliefert, welches uns ermöglicht, für unser Projekt Namen und Web-Adresse in der Datenbank zu spezifieren. Wir können auch mehrere solcher ``Sites`` anlegen und könnten dann in Abhängigkeit von der genutzten Domain unterschiedlichen Content ausgeben. Das wollen wir hier in diesem Buch allerdings nicht weiter vertiefen, uns reicht die Möglichkeit, einen festen Namen und eine Web-Adresse in der Admin zu hinterlegen. Um das Sites-Framework zu installieren, müssen wir es nur in den ``INSTALLED_APPS`` in den ``event_manager/event_manager/settings/base.py`` eintragen. .. code-block:: python INSTALLED_APPS = [ ... "django.contrib.sites", ... ] und ebenfalls in der ``event_manager/event_manager/settings/base.py`` die Middleware hinzufügen. .. code-block:: python MIDDLEWARE = [ ... "django.contrib.sites.middleware.CurrentSiteMiddleware", ... ] Nun führen wir die Migration aus: .. code-block:: bash (eventenv) python manage.py migrate Running migrations: Applying sites.0001_initial... OK Applying sites.0002_alter_domain_unique... OK und schon ist das ``Sites-Framework`` installiert. In den Settings unter ``event_manager/event_manager/settings/base.py`` können wir jetzt noch die SITE_ID festlegen. Diese setzen wir auf 1 (weil wir auch nur eine Site festlegen). .. code-block:: python SITE_ID = 1 Die Admin Oberfläche ---------------------- Wenn wir jetzt die Administrationsoberfläche öffnen, sehen wir auf der linken Seite einen neuen Eintrag namens ``Webseiten``. .. image:: /images/django_sites_1.png Wir können jetzt den Namen der Webseite (Anzeigename) und die Adresse ändern und speichern. Momentan hat das noch keinen Einfluss auf unsere Website, da wir die Daten bisher nicht ausgeben. .. image:: /images/django_sites_2.png Unser Context Processor ------------------------ Wir wollen den ``Anzeigename`` unserer ``Site`` jetzt in jeder View ausgeben. Dazu entwickeln wir unseren ersten eigenen Kontext-Prozessor. Unter ``event_manager/events/`` legen wir die Datei ``context_processors.py`` an. Diese Datei enthält eine Funktion, die ein Kontext-Dictionary zurückgibt. .. code-block:: python from django.contrib.sites.models import Site def get_site_infos(request): current_site = Site.objects.get_current() return {'site_name':current_site} ``get_site_infos"`` ist ein benutzerdefinierter Kontextprozessor, den wir gerade erstellt haben. Wir können diesen jetzt den ``context_processors`` in den ``TEMPLATES"``-Settings unter ``event_manager/eventmanager/settings/base.py`` hinzufügen. Der Key ``site_name`` aus dem zurückgegebenem Dictionary ist dann als Template-Variable in allen Templates zugänglich. .. code-block:: python TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "event_manager" / "templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", "events.context_processors.get_site_infos", ], }, }, ] Das Template anpassen ---------------------- Wir wollen den Website-Namen jetzt überall auf unserer Website ausgeben. Deshalb öffnen wir das base-Template unter ``event_manager/event_manager/templates/base.html`` und geben die Kontextvariable ``site_name`` aus. Ersetze jetzt das Wort EVENTR in Zeile durch: .. code-block:: html+django {{site_name}} Wenn wir die Website unter ``http://127.0.0.1`` neu laden, sollte der Name der Webseite oben links als Logo erscheinen. https://dev.to/gilbishkosma/custom-context-processors-in-django-3c93