gwift-book/chapters/contexts-processors.tex

80 lines
3.8 KiB
TeX
Executable File

\chapter{Context Processors}
Mise en pratique: un \emph{context processor} sert \emph{grosso-modo} à peupler l'ensemble des données transmises des vues aux templates avec des données communes.
Un context processor est un peu l'équivalent d'un middleware, mais entre les données et les templates, là où le middleware va s'occuper des données relatives aux réponses et requêtes elles-mêmes.
Un \emph{context processor} sert \emph{grosso-modo} à peupler l'ensemble des données transmises des vues aux templates avec des données communes. Un context processor est un peu l'équivalent d'un middleware, mais est situé entre les données et les templates, là où le middleware va s'occuper des données relatives aux réponses et requêtes elles-mêmes.
Nous vous proposons deux exemples ci-dessous:
\begin{enumerate}
\item
Le premier récupère le numéro de version de \texttt{Git}.
Ce n'est sans doute pas le plus adéquat à réaliser en production, puisqu'il suffirait que Git ne soit pas installé, que le code ait été déployé d'une autre manière ou d'un soucis de performances.
\item
Le second qui récupère la liste des catégories et sous-catégories d'une base de données fictives.
Ces deux informations pourraient être affichées pour chaque utilisateur et chaque requête faite vers l'application.
Dans l'immédiat, ce n'est pas trop lourd, mais vu que ces informations ne dépendent pas de l'utilisateur, nous pouvons les glisser dans le cache pour faire gagner énormément de temps.
\end{enumerate}
\begin{minted}{python}
# core/context_processors.py
import subprocess
def git_describe(request) -> str:
return {
"git_describe": subprocess.check_output(
["git", "describe", "--always"]
).strip(),
"git_date": subprocess.check_output(
[
"git",
"show",
"-s",
r"--format=%cd",
r"--date=format:%d-%m-%Y"
]
),
}
\end{minted}
Ceci aura pour effet d'ajouter les deux variables \texttt{git\_describe} et \texttt{git\_date} dans tous les contextes de tous les templates de l'application.
\begin{minted}{python}
from product.models import SubCategory, Category
def add_variable_to_context(request):
return {
'subCategories': SubCategory.objects.order_by('id').all(),
'categories': Category.objects.order_by("id").all(),
}
\end{minted}
Il convient ensuite d'ajouter ces \textit{context processors} au niveau des options de configuration des templates:
\begin{minted}{python}
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "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",
"..."
"core.context_processors.git_describe",
"core.context_processors.add_variable_to_context",
"...",
],
},
},
]
\end{minted}
Les context processors sont extrêmement utiles pour injecter des données dans chacune des vues.
Il peut cependant être utile d'utiliser un mécanisme de cache pour gagner du temps de traitement, surtout lorsque des appels en base de données doivent être réalisés: ceci évite que ces appels ne soient réalisés trop souvent, alors qu'ils n'évoluent peut-être pas aussi vite.