Implémentation d’un moteur de gabarits personnalisé

Moteurs personnalisés

Voici comment implémenter un moteur de gabarit personnalisé afin d’utiliser un autre système de gabarits. Un moteur de gabarit est une classe qui hérite de django.template.backends.base.BaseEngine. Elle doit implémenter get_template()` et, facultativement, from_string(). Voici un exemple d’une bibliothèque de gabarit fictive foobar:

from django.template import TemplateDoesNotExist, TemplateSyntaxError
from django.template.backends.base import BaseEngine
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy

import foobar


class FooBar(BaseEngine):
    # Name of the subdirectory containing the templates for this engine
    # inside an installed application.
    app_dirname = "foobar"

    def __init__(self, params):
        params = params.copy()
        options = params.pop("OPTIONS").copy()
        super().__init__(params)

        self.engine = foobar.Engine(**options)

    def from_string(self, template_code):
        try:
            return Template(self.engine.from_string(template_code))
        except foobar.TemplateCompilationFailed as exc:
            raise TemplateSyntaxError(exc.args)

    def get_template(self, template_name):
        try:
            return Template(self.engine.get_template(template_name))
        except foobar.TemplateNotFound as exc:
            raise TemplateDoesNotExist(exc.args, backend=self)
        except foobar.TemplateCompilationFailed as exc:
            raise TemplateSyntaxError(exc.args)


class Template:
    def __init__(self, template):
        self.template = template

    def render(self, context=None, request=None):
        if context is None:
            context = {}
        if request is not None:
            context["request"] = request
            context["csrf_input"] = csrf_input_lazy(request)
            context["csrf_token"] = csrf_token_lazy(request)
        return self.template.render(context)

Voir DEP 182 pour plus d’informations.

Intégration du débogage pour les moteurs personnalisés

La page de débogage de Django présente des points d’entrée pour fournir des informations détaillées lorsqu’une erreur de gabarit se produit. Les moteurs de gabarit personnalisés peuvent utiliser ces points d’entrée pour améliorer les informations d’erreur qui sont présentées aux utilisateurs. Les points d’entrée suivants sont disponibles :

Gabarit postmortem

Le gabarit postmortem apparaît lorsque TemplateDoesNotExist est générée. Il présente la liste des moteurs et chargeurs de gabarit utilisés lors de la recherche du gabarit concerné. Par exemple, si deux moteurs Django sont configurés, le gabarit postmortem ressemble à ceci :

../../_images/postmortem.png

Les moteurs personnalisés peuvent remplir le gabarit postmortem en passant les paramètres backend et tried lors de la génération de TemplateDoesNotExist. Les moteurs qui utilisent le gabarit postmortem doivent indiquer une origine sur l’objet de gabarit.

Information de ligne contextuelle

Si une erreur se produit pendant l’analyse et le rendu d’un gabarit, Django peut afficher la ligne à laquelle s’est produite l’erreur. Par exemple :

../../_images/template-lines.png

Les moteurs personnalisés peuvent fournir cette information en définissant un attribut template_debug sur les exceptions générées pendant l’analyse et le rendu. Cet attribut est un dict possédant les valeurs suivantes :

  • 'name': le nom du gabarit dans lequel l’exception s’est produite.
  • 'message': le message de l’exception.
  • 'source_lines': les lignes précédentes, suivantes ainsi que la ligne elle-même où s’est produite l’exception. C’est pour fournir du contexte, il ne faut donc pas inclure plus d’une vingtaine de lignes.
  • 'line': le numéro de ligne à laquelle s’est produite l’exception.
  • 'before': le contenu de la ligne ayant provoqué l’erreur, avant le symbole qui a produit l’erreur.
  • 'during': le symbole qui a généré l’erreur.
  • 'after': le contenu de la ligne ayant provoqué l’erreur, après le symbole qui a produit l’erreur.
  • 'total': le nombre de lignes dans source_lines.
  • 'top': le numéro de ligne où source_lines commence.
  • 'bottom': le numéro de ligne où source_lines se termine.

Étant donné l’erreur de gabarit ci-dessus, template_debug ressemblerait à ceci :

{
    "name": "/path/to/template.html",
    "message": "Invalid block tag: 'syntax'",
    "source_lines": [
        (1, "some\n"),
        (2, "lines\n"),
        (3, "before\n"),
        (4, "Hello {% syntax error %} {{ world }}\n"),
        (5, "some\n"),
        (6, "lines\n"),
        (7, "after\n"),
        (8, ""),
    ],
    "line": 4,
    "before": "Hello ",
    "during": "{% syntax error %}",
    "after": " {{ world }}\n",
    "total": 9,
    "bottom": 9,
    "top": 1,
}

API d’origine et intégration tierce

Les gabarits Django possèdent un objet Origin accessible par leur attribut template.origin. Ceci permet aux informations de débogage d’apparaître dans le gabarit postmortem, de même que dans des bibliothèques tierces, telle que Django Debug Toolbar.

Les moteurs personnalisés peuvent fournir leurs propres informations template.origin en créant un objet qui définit les attributs suivants :

  • 'name': le chemin complet vers le gabarit.
  • 'template_name': le chemin relatif vers le gabarit tel que transmis aux méthodes de chargement de gabarits.
  • 'loader_name': une chaîne facultative identifiant la fonction ou la classe utilisée pour charger le gabarit, par exemple django.template.loaders.filesystem.Loader.
Back to Top