Le moteur de rendu Jinja2 (renderer.py) dans Forge¶
Ce document explique le moteur de rendu Jinja2 de Forge, porté par integrations/jinja2/renderer.py.
C'est l'implémentation concrète qui transforme un gabarit et un contexte en HTML.
1. Rôle du module¶
Jinja2Renderer est l'adaptateur entre Forge et le moteur de templates Jinja2.
Il implémente le contrat de rendu attendu par core.templating : une méthode render(template, context) qui retourne du HTML.
Autour de Jinja2, il ajoute quatre choses propres à Forge : un loader composite (projet + opt-ins), l'échappement automatique de sécurité, des variables globales injectées dans tous les gabarits, et la conversion des erreurs vers l'exception publique de Forge.
2. Vue d'ensemble rapide¶
| Élément | Valeur |
|---|---|
| Classe | Jinja2Renderer |
| Module | integrations.jinja2.renderer |
| Couche | Intégration (templating) |
| Rôle | rendre un gabarit Jinja2 en HTML pour les contrôleurs |
| Implémente | le contrat de rendu de core.templating |
| Enregistré par | core.templating.manager (via template_manager.register(...)) |
| Construit par | core.app.app_factory et le app.py du squelette |
| Loader | _OptinAwareLoader : mvc/views/ puis les loaders d'opt-in (ADR-046) |
| Dépend de | jinja2, core.forge (routeur), core.security.csp (nonce) |
| Exception levée | core.templating.errors.TemplateNotFoundError (DX-RENDER-ERROR-001) |
| Sécurité | autoescape pour toutes les extensions et chaînes (SEC-JINJA-AUTOESCAPE-001) |
3. Schémas UML¶
Les deux schémas montrent la structure du renderer et le déroulé d'un rendu.
3.1 Diagramme de classe¶
Le diagramme de classe montre le renderer, son loader composite et son environnement Jinja2.
classDiagram
direction LR
class Jinja2Renderer {
-Environment _env
-str _views_dir
+__init__(views_dir)
+render(template, context) str
}
class _OptinAwareLoader {
-FileSystemLoader _project
+get_source(env, template)
+list_templates() list
}
class Environment {
globals (url_for, csp_nonce, trans, ...)
autoescape
}
class TemplateManager {
+register(renderer)
}
Jinja2Renderer --> Environment : configure
Environment --> _OptinAwareLoader : résout les gabarits
TemplateManager --> Jinja2Renderer : enregistre
Jinja2Renderer ..> TemplateNotFoundError : gabarit introuvable
À retenir :
Jinja2Renderern'expose qu'un constructeur etrender(...);- le loader composite cherche d'abord dans
mvc/views/, puis dans les opt-ins ; - l'environnement Jinja2 porte les globals et l'autoescape ;
- une erreur de gabarit est convertie en
TemplateNotFoundError(exception publique de Forge).
3.2 Diagramme de séquence¶
Le diagramme de séquence montre la résolution d'un gabarit à travers la chaîne de loaders.
sequenceDiagram
participant Ctrl as Contrôleur
participant R as Jinja2Renderer
participant L as _OptinAwareLoader
participant Optins as Loaders d'opt-in
Ctrl->>R: render("article/show.html", contexte)
R->>L: get_source(...)
L->>L: cherche dans mvc/views/
alt trouvé dans le projet
L-->>R: source du gabarit
else absent du projet
L->>Optins: get_source(...) (registre relu à chaud)
Optins-->>L: source ou TemplateNotFound
L-->>R: source du gabarit
end
R-->>Ctrl: HTML rendu
Note over R: si introuvable partout, TemplateNotFoundError
À retenir :
- le dossier
mvc/views/est prioritaire : on peut surcharger un gabarit d'opt-in ; - la liste des loaders d'opt-in est relue à chaque résolution (l'ordre d'import des paquets n'importe pas) ;
- introuvable partout, le rendu lève
TemplateNotFoundError, pas l'erreur brute de Jinja2.
4. API publique¶
| Membre | Signature | Rôle |
|---|---|---|
Jinja2Renderer |
Jinja2Renderer(views_dir: str) |
construit le renderer pour un dossier de vues |
render |
render(template: str, context: dict) -> str |
rend le gabarit et retourne le HTML ; lève TemplateNotFoundError si absent |
5. Variables globales injectées¶
Ces variables sont disponibles dans tous les gabarits, sans les passer explicitement.
| Global | Valeur par défaut | Rôle |
|---|---|---|
url_for |
résout via le routeur actif | construit une URL à partir d'un nom de route |
csp_nonce |
nonce de la requête, sinon "" |
nonce CSP pour les scripts inline |
current_user |
None |
utilisateur courant (renseigné par l'application) |
is_authenticated |
False |
drapeau d'authentification |
can |
refuse tout (_deny) |
contrôle d'accès (enrichi par l'opt-in RBAC) |
trans |
repli no-op (retourne la clé) | traduction ; remplacé par l'opt-in forge-mvc-i18n (ADR-027) |
Helpers d'opt-in
Si forge-mvc-i18n est installé, trans charge les vrais catalogues JSON.
Si forge-mvc-workflow est installé, ses helpers Jinja sont ajoutés aux globals.
Ces enrichissements sont optionnels : sans les opt-ins, les gabarits générés rendent quand même.
6. Contextes d'utilisation¶
| Besoin | Élément |
|---|---|
| Enregistrer le moteur au démarrage | template_manager.register(Jinja2Renderer(views_dir)) |
| Rendre une vue dans un contrôleur | BaseController.render(...) (qui délègue au renderer) |
| Surcharger un gabarit d'opt-in | placer un fichier de même chemin dans mvc/views/ |
| Construire une URL dans un gabarit | {{ url_for("article-show", id=1) }} |
7. Exemples d'utilisation¶
7.1 Enregistrer le renderer au démarrage¶
from integrations.jinja2.renderer import Jinja2Renderer
from core.templating.manager import template_manager
template_manager.register(Jinja2Renderer("mvc/views"))
C'est ce que fait core.app.app_factory (et le app.py du squelette).
7.2 Rendre un gabarit¶
renderer = Jinja2Renderer("mvc/views")
html = renderer.render("article/show.html", {"article": article})
Échappement automatique global
L'autoescape est actif pour toutes les extensions et les chaînes, pas seulement .html (SEC-JINJA-AUTOESCAPE-001).
Pour insérer du HTML voulu, utilisez explicitement le filtre | safe.
Surcharge par le projet
Le dossier mvc/views/ est consulté en premier.
Un fichier de même chemin que celui d'un opt-in remplace le gabarit par défaut du paquet.
Voir aussi¶
- Le contrat et le gestionnaire de templating
core.templating(manager,contracts,errors) : ce que le renderer implémente et l'exception qu'il lève. - Le registre de configuration
core.forge: fournit le routeur actif utilisé parurl_for. - ADR-046 (loaders de templates Jinja pour les opt-ins) et ADR-027 (extraction i18n, repli no-op du noyau).