{"title":"Moteur de gabarit personnalisé","version":"3.1","locale":"fr","docname":"howto/custom-template-backend","url":"/fr/3.1/howto/custom-template-backend/","canonical":"https://djangodocs.dev/fr/3.1/howto/custom-template-backend/","summary":"Moteurs personnalisés Lien vers cette rubrique # Voici comment implémenter un moteur de gabarit personnalisé afin d’utiliser un autre système de gabarits. Un moteur…","html":"<h1>Moteur de gabarit personnalisé<a class=\"heading-anchor\" href=\"#custom-template-backend\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<section id=\"custom-backends\">\n<h2>Moteurs personnalisés<a class=\"heading-anchor\" href=\"#custom-backends\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>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 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.backends.base.BaseEngine</span></code>. Elle doit implémenter get_template()` et, facultativement, <code class=\"docutils literal notranslate\"><span class=\"pre\">from_string()</span></code>. Voici un exemple d’une bibliothèque de gabarit fictive <code class=\"docutils literal notranslate\"><span class=\"pre\">foobar</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TemplateDoesNotExist</span><span class=\"p\">,</span> <span class=\"n\">TemplateSyntaxError</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template.backends.base</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseEngine</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template.backends.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">csrf_input_lazy</span><span class=\"p\">,</span> <span class=\"n\">csrf_token_lazy</span>\n\n<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">foobar</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">FooBar</span><span class=\"p\">(</span><span class=\"n\">BaseEngine</span><span class=\"p\">):</span>\n\n    <span class=\"c1\"># Name of the subdirectory containing the templates for this engine</span>\n    <span class=\"c1\"># inside an installed application.</span>\n    <span class=\"n\">app_dirname</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;foobar&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">params</span><span class=\"p\">):</span>\n        <span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"n\">params</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n        <span class=\"n\">options</span> <span class=\"o\">=</span> <span class=\"n\">params</span><span class=\"o\">.</span><span class=\"n\">pop</span><span class=\"p\">(</span><span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"n\">params</span><span class=\"p\">)</span>\n\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">engine</span> <span class=\"o\">=</span> <span class=\"n\">foobar</span><span class=\"o\">.</span><span class=\"n\">Engine</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">options</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">from_string</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">template_code</span><span class=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">Template</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">engine</span><span class=\"o\">.</span><span class=\"n\">from_string</span><span class=\"p\">(</span><span class=\"n\">template_code</span><span class=\"p\">))</span>\n        <span class=\"k\">except</span> <span class=\"n\">foobar</span><span class=\"o\">.</span><span class=\"n\">TemplateCompilationFailed</span> <span class=\"k\">as</span> <span class=\"n\">exc</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span><span class=\"n\">exc</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_template</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">template_name</span><span class=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">Template</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">engine</span><span class=\"o\">.</span><span class=\"n\">get_template</span><span class=\"p\">(</span><span class=\"n\">template_name</span><span class=\"p\">))</span>\n        <span class=\"k\">except</span> <span class=\"n\">foobar</span><span class=\"o\">.</span><span class=\"n\">TemplateNotFound</span> <span class=\"k\">as</span> <span class=\"n\">exc</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">TemplateDoesNotExist</span><span class=\"p\">(</span><span class=\"n\">exc</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"n\">backend</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"p\">)</span>\n        <span class=\"k\">except</span> <span class=\"n\">foobar</span><span class=\"o\">.</span><span class=\"n\">TemplateCompilationFailed</span> <span class=\"k\">as</span> <span class=\"n\">exc</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span><span class=\"n\">exc</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Template</span><span class=\"p\">:</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">template</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"n\">template</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"n\">context</span> <span class=\"ow\">is</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n        <span class=\"k\">if</span> <span class=\"n\">request</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;request&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">request</span>\n            <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;csrf_input&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">csrf_input_lazy</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span>\n            <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;csrf_token&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">csrf_token_lazy</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Voir <a class=\"reference external\" href=\"https://github.com/django/deps/blob/main/final/0182-multiple-template-engines.rst\">DEP 182</a> pour plus d’informations.</p>\n</section>\n<section id=\"debug-integration-for-custom-engines\">\n<span id=\"template-debug-integration\"></span><h2>Intégration du débogage pour les moteurs personnalisés<a class=\"heading-anchor\" href=\"#debug-integration-for-custom-engines\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>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 :</p>\n<section id=\"template-postmortem\">\n<span id=\"id1\"></span><h3>Gabarit postmortem<a class=\"heading-anchor\" href=\"#template-postmortem\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le gabarit postmortem apparaît lorsque <a class=\"reference internal\" href=\"/fr/3.1/topics/templates/#django.template.TemplateDoesNotExist\" title=\"django.template.TemplateDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">TemplateDoesNotExist</span></code></a> 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 :</p>\n<img alt=\"/fr/3.1/_images/postmortem.png\" src=\"/fr/3.1/_images/postmortem.png\" />\n<p>Les moteurs personnalisés peuvent remplir le gabarit postmortem en passant les paramètres <code class=\"docutils literal notranslate\"><span class=\"pre\">backend</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">tried</span></code> lors de la génération de <a class=\"reference internal\" href=\"/fr/3.1/topics/templates/#django.template.TemplateDoesNotExist\" title=\"django.template.TemplateDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">TemplateDoesNotExist</span></code></a>. Les moteurs qui utilisent le gabarit postmortem <a class=\"reference internal\" href=\"#template-origin-api\"><span class=\"std std-ref\">doivent indiquer une origine</span></a> sur l’objet de gabarit.</p>\n</section>\n<section id=\"contextual-line-information\">\n<h3>Information de ligne contextuelle<a class=\"heading-anchor\" href=\"#contextual-line-information\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>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 :</p>\n<img alt=\"/fr/3.1/_images/template-lines.png\" src=\"/fr/3.1/_images/template-lines.png\" />\n<p>Les moteurs personnalisés peuvent fournir cette information en définissant un attribut <code class=\"docutils literal notranslate\"><span class=\"pre\">template_debug</span></code> sur les exceptions générées pendant l’analyse et le rendu. Cet attribut est un <a class=\"reference external\" href=\"https://docs.python.org/3/library/stdtypes.html#dict\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">dict</span></code></a> possédant les valeurs suivantes :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'name'</span></code>: le nom du gabarit dans lequel l’exception s’est produite.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'message'</span></code>: le message de l’exception.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'source_lines'</span></code>: 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.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'line'</span></code>: le numéro de ligne à laquelle s’est produite l’exception.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'before'</span></code>: le contenu de la ligne ayant provoqué l’erreur, avant le symbole qui a produit l’erreur.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'during'</span></code>: le symbole qui a généré l’erreur.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'after'</span></code>: le contenu de la ligne ayant provoqué l’erreur, après le symbole qui a produit l’erreur.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'total'</span></code>: le nombre de lignes dans <code class=\"docutils literal notranslate\"><span class=\"pre\">source_lines</span></code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'top'</span></code>: le numéro de ligne où <code class=\"docutils literal notranslate\"><span class=\"pre\">source_lines</span></code> commence.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'bottom'</span></code>: le numéro de ligne où <code class=\"docutils literal notranslate\"><span class=\"pre\">source_lines</span></code> se termine.</p></li>\n</ul>\n<p>Étant donné l’erreur de gabarit ci-dessus, <code class=\"docutils literal notranslate\"><span class=\"pre\">template_debug</span></code> ressemblerait à ceci :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"p\">{</span>\n    <span class=\"s1\">&#39;name&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;/path/to/template.html&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;message&#39;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Invalid block tag: &#39;syntax&#39;&quot;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;source_lines&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"s1\">&#39;some</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"s1\">&#39;lines</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"s1\">&#39;before</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Hello {</span><span class=\"si\">% s</span><span class=\"s1\">yntax error %} {{ world }}</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"s1\">&#39;some</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">6</span><span class=\"p\">,</span> <span class=\"s1\">&#39;lines</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"s1\">&#39;after</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">],</span>\n    <span class=\"s1\">&#39;line&#39;</span><span class=\"p\">:</span> <span class=\"mi\">4</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;before&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;Hello &#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;during&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;{</span><span class=\"si\">% s</span><span class=\"s1\">yntax error %}&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;after&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39; {{ world }}</span><span class=\"se\">\\n</span><span class=\"s1\">&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;total&#39;</span><span class=\"p\">:</span> <span class=\"mi\">9</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;bottom&#39;</span><span class=\"p\">:</span> <span class=\"mi\">9</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;top&#39;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</section>\n<section id=\"origin-api-and-3rd-party-integration\">\n<span id=\"template-origin-api\"></span><h3>API d’origine et intégration tierce<a class=\"heading-anchor\" href=\"#origin-api-and-3rd-party-integration\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les gabarits Django possèdent un objet <a class=\"reference internal\" href=\"/fr/3.1/ref/templates/api/#django.template.base.Origin\" title=\"django.template.base.Origin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Origin</span></code></a> accessible par leur attribut <code class=\"docutils literal notranslate\"><span class=\"pre\">template.origin</span></code>. Ceci permet aux informations de débogage d’apparaître dans le <a class=\"reference internal\" href=\"#template-postmortem\"><span class=\"std std-ref\">gabarit postmortem</span></a>, de même que dans des bibliothèques tierces, telle que <a class=\"reference external\" href=\"https://github.com/jazzband/django-debug-toolbar\">Django Debug Toolbar</a>.</p>\n<p>Les moteurs personnalisés peuvent fournir leurs propres informations <code class=\"docutils literal notranslate\"><span class=\"pre\">template.origin</span></code> en créant un objet qui définit les attributs suivants :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'name'</span></code>: le chemin complet vers le gabarit.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'template_name'</span></code>: le chemin relatif vers le gabarit tel que transmis aux méthodes de chargement de gabarits.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'loader_name'</span></code>: une chaîne facultative identifiant la fonction ou la classe utilisée pour charger le gabarit, par exemple <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.loaders.filesystem.Loader</span></code>.</p></li>\n</ul>\n</section>\n</section>","rootId":"custom-template-backend","toc":[{"title":"Moteurs personnalisés","anchor":"custom-backends","children":[]},{"title":"Intégration du débogage pour les moteurs personnalisés","anchor":"debug-integration-for-custom-engines","children":[{"title":"Gabarit postmortem","anchor":"template-postmortem","children":[]},{"title":"Information de ligne contextuelle","anchor":"contextual-line-information","children":[]},{"title":"API d’origine et intégration tierce","anchor":"origin-api-and-3rd-party-integration","children":[]}]}],"breadcrumbs":[{"docname":"howto/index","title":"Guides pratiques","url":"/fr/3.1/howto/"}],"prev":{"docname":"howto/custom-lookups","title":"Expressions de recherche personnalisées","url":"/fr/3.1/howto/custom-lookups/"},"next":{"docname":"howto/custom-template-tags","title":"Balises et filtres de gabarit personnalisés","url":"/fr/3.1/howto/custom-template-tags/"},"formats":{"html":"/fr/3.1/howto/custom-template-backend/","markdown":"/fr/3.1/howto/custom-template-backend.md","json":"/fr/3.1/howto/custom-template-backend.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/howto/custom-template-backend.txt","official":"https://docs.djangoproject.com/fr/3.1/howto/custom-template-backend/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}