{"title":"Implémentation d’un moteur de gabarits personnalisé","version":"5.0","locale":"fr","docname":"howto/custom-template-backend","url":"/fr/5.0/howto/custom-template-backend/","canonical":"https://djangodocs.dev/fr/5.0/howto/custom-template-backend/","summary":"Voici comment implémenter un moteur de gabarit personnalisé afin d’utiliser un autre système de gabarits.","html":"<h1>Implémentation d’un moteur de gabarits personnalisé<a class=\"heading-anchor\" href=\"#how-to-implement-a-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\">django.template.backends.base.BaseEngine</code>. Elle doit implémenter get_template()` et, facultativement, <code class=\"docutils literal notranslate\">from_string()</code>. Voici un exemple d’une bibliothèque de gabarit fictive <code class=\"docutils literal notranslate\">foobar</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=\"nn\">django.template</span> <span class=\"kn\">import</span> TemplateDoesNotExist<span class=\"p\">,</span> TemplateSyntaxError\n<span class=\"kn\">from</span> <span class=\"nn\">django.template.backends.base</span> <span class=\"kn\">import</span> BaseEngine\n<span class=\"kn\">from</span> <span class=\"nn\">django.template.backends.utils</span> <span class=\"kn\">import</span> csrf_input_lazy<span class=\"p\">,</span> csrf_token_lazy\n\n<span class=\"kn\">import</span> <span class=\"nn\">foobar</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">FooBar</span><span class=\"p\">(</span>BaseEngine<span class=\"p\">):</span>\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    app_dirname <span class=\"o\">=</span> <span class=\"s2\">&quot;foobar&quot;</span>\n\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> params<span class=\"p\">):</span>\n        params <span class=\"o\">=</span> params<span class=\"o\">.</span>copy<span class=\"p\">()</span>\n        options <span class=\"o\">=</span> params<span class=\"o\">.</span>pop<span class=\"p\">(</span><span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">)</span><span class=\"o\">.</span>copy<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>params<span class=\"p\">)</span>\n\n        <span class=\"bp\">self</span><span class=\"o\">.</span>engine <span class=\"o\">=</span> foobar<span class=\"o\">.</span>Engine<span class=\"p\">(</span><span class=\"o\">**</span>options<span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">from_string</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> template_code<span class=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> Template<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>engine<span class=\"o\">.</span>from_string<span class=\"p\">(</span>template_code<span class=\"p\">))</span>\n        <span class=\"k\">except</span> foobar<span class=\"o\">.</span>TemplateCompilationFailed <span class=\"k\">as</span> exc<span class=\"p\">:</span>\n            <span class=\"k\">raise</span> TemplateSyntaxError<span class=\"p\">(</span>exc<span class=\"o\">.</span>args<span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get_template</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> template_name<span class=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> Template<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>engine<span class=\"o\">.</span>get_template<span class=\"p\">(</span>template_name<span class=\"p\">))</span>\n        <span class=\"k\">except</span> foobar<span class=\"o\">.</span>TemplateNotFound <span class=\"k\">as</span> exc<span class=\"p\">:</span>\n            <span class=\"k\">raise</span> TemplateDoesNotExist<span class=\"p\">(</span>exc<span class=\"o\">.</span>args<span class=\"p\">,</span> backend<span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"p\">)</span>\n        <span class=\"k\">except</span> foobar<span class=\"o\">.</span>TemplateCompilationFailed <span class=\"k\">as</span> exc<span class=\"p\">:</span>\n            <span class=\"k\">raise</span> TemplateSyntaxError<span class=\"p\">(</span>exc<span class=\"o\">.</span>args<span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Template</span><span class=\"p\">:</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> template<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>template <span class=\"o\">=</span> template\n\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> request<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> context <span class=\"ow\">is</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            context <span class=\"o\">=</span> <span class=\"p\">{}</span>\n        <span class=\"k\">if</span> request <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            context<span class=\"p\">[</span><span class=\"s2\">&quot;request&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> request\n            context<span class=\"p\">[</span><span class=\"s2\">&quot;csrf_input&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> csrf_input_lazy<span class=\"p\">(</span>request<span class=\"p\">)</span>\n            context<span class=\"p\">[</span><span class=\"s2\">&quot;csrf_token&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> csrf_token_lazy<span class=\"p\">(</span>request<span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>template<span class=\"o\">.</span>render<span class=\"p\">(</span>context<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/5.0/topics/templates/#django.template.TemplateDoesNotExist\" title=\"django.template.TemplateDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\">TemplateDoesNotExist</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/5.0/_images/postmortem.png\" src=\"/fr/5.0/_images/postmortem.png\" />\n<p>Les moteurs personnalisés peuvent remplir le gabarit postmortem en passant les paramètres <code class=\"docutils literal notranslate\">backend</code> et <code class=\"docutils literal notranslate\">tried</code> lors de la génération de <a class=\"reference internal\" href=\"/fr/5.0/topics/templates/#django.template.TemplateDoesNotExist\" title=\"django.template.TemplateDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\">TemplateDoesNotExist</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/5.0/_images/template-lines.png\" src=\"/fr/5.0/_images/template-lines.png\" />\n<p>Les moteurs personnalisés peuvent fournir cette information en définissant un attribut <code class=\"docutils literal notranslate\">template_debug</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\">dict</code></a> possédant les valeurs suivantes :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">'name'</code>: le nom du gabarit dans lequel l’exception s’est produite.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'message'</code>: le message de l’exception.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'source_lines'</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\">'line'</code>: le numéro de ligne à laquelle s’est produite l’exception.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'before'</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\">'during'</code>: le symbole qui a généré l’erreur.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'after'</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\">'total'</code>: le nombre de lignes dans <code class=\"docutils literal notranslate\">source_lines</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'top'</code>: le numéro de ligne où <code class=\"docutils literal notranslate\">source_lines</code> commence.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'bottom'</code>: le numéro de ligne où <code class=\"docutils literal notranslate\">source_lines</code> se termine.</p></li>\n</ul>\n<p>Étant donné l’erreur de gabarit ci-dessus, <code class=\"docutils literal notranslate\">template_debug</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=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;/path/to/template.html&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;message&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Invalid block tag: &#39;syntax&#39;&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;source_lines&quot;</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=\"s2\">&quot;some</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"s2\">&quot;lines</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"s2\">&quot;before</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Hello {</span><span class=\"si\">% s</span><span class=\"s2\">yntax error %} {{ world }}</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"s2\">&quot;some</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">6</span><span class=\"p\">,</span> <span class=\"s2\">&quot;lines</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"s2\">&quot;after</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">],</span>\n    <span class=\"s2\">&quot;line&quot;</span><span class=\"p\">:</span> <span class=\"mi\">4</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;before&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Hello &quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;during&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;{</span><span class=\"si\">% s</span><span class=\"s2\">yntax error %}&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;after&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot; {{ world }}</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;total&quot;</span><span class=\"p\">:</span> <span class=\"mi\">9</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;bottom&quot;</span><span class=\"p\">:</span> <span class=\"mi\">9</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;top&quot;</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/5.0/ref/templates/api/#django.template.base.Origin\" title=\"django.template.base.Origin\"><code class=\"xref py py-class docutils literal notranslate\">Origin</code></a> accessible par leur attribut <code class=\"docutils literal notranslate\">template.origin</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\">template.origin</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\">'name'</code>: le chemin complet vers le gabarit.</p></li>\n<li><p><code class=\"docutils literal notranslate\">'template_name'</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\">'loader_name'</code>: une chaîne facultative identifiant la fonction ou la classe utilisée pour charger le gabarit, par exemple <code class=\"docutils literal notranslate\">django.template.loaders.filesystem.Loader</code>.</p></li>\n</ul>\n</section>\n</section>","rootId":"how-to-implement-a-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/5.0/howto/"}],"prev":{"docname":"howto/custom-lookups","title":"Écriture d’expressions de requêtes personnalisées","url":"/fr/5.0/howto/custom-lookups/"},"next":{"docname":"howto/custom-template-tags","title":"Création de balises et filtres de gabarit personnalisés","url":"/fr/5.0/howto/custom-template-tags/"},"formats":{"html":"/fr/5.0/howto/custom-template-backend/","markdown":"/fr/5.0/howto/custom-template-backend.md","json":"/fr/5.0/howto/custom-template-backend.json"},"source":"https://github.com/django/django/blob/stable/5.0.x/docs/howto/custom-template-backend.txt","official":"https://docs.djangoproject.com/fr/5.0/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","it","pt-br","ko","es","el","pl"]}