# Documentation Django 3.1.9.dev

# Moteur de gabarit 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 :

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 :

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`.