{"title":"Balises et filtres de gabarit personnalisés","version":"1.9","locale":"fr","docname":"howto/custom-template-tags","url":"/fr/1.9/howto/custom-template-tags/","canonical":"https://djangodocs.dev/fr/1.9/howto/custom-template-tags/","summary":"Le langage de gabarits de Django offre une large palette de balises et filtres intégrés conçus pour répondre aux besoins de la logique de présentation de votre…","html":"<h1>Balises et filtres de gabarit personnalisés<a class=\"heading-anchor\" href=\"#custom-template-tags-and-filters\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Le langage de gabarits de Django offre une large palette de <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/\"><span class=\"doc\">balises et filtres intégrés</span></a> conçus pour répondre aux besoins de la logique de présentation de votre application. Néanmoins, il se peut que vous rencontriez des besoins non couverts par cet ensemble de fonctions de gabarits. Il est possible d’étendre le moteur de gabarit en définissant des balises et des filtres personnalisés en Python, puis en les rendant disponibles dans vos gabarits par la balise <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">load</span> <span class=\"pre\">%}</span></code></a>.</p>\n<section id=\"code-layout\">\n<h2>Disposition du code<a class=\"heading-anchor\" href=\"#code-layout\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>L’endroit le plus souvent utilisé pour placer des balises et filtres de gabarit personnalisés est à l’intérieur d’une application Django. S’ils sont liés à une application existante, il est logique de les y intégrer ; sinon, ils peuvent être ajoutés à une nouvelle application. Lorsqu’une application Django est ajoutée à <a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>, toute balise qu’elle définit à l’endroit conventionnel présenté ci-dessous est automatiquement mise à disposition du chargement depuis les gabarits.</p>\n<p>L’application doit contenir un répertoire <code class=\"docutils literal notranslate\"><span class=\"pre\">templatetags</span></code> au même niveau que <code class=\"docutils literal notranslate\"><span class=\"pre\">models.py</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">views.py</span></code>, etc. S’il n’existe pas encore, créez-le, sans oublier le fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__.py</span></code> pour que le répertoire soit bien considéré comme un paquet Python.</p>\n<aside class=\"admonition-development-server-won-t-automatically-restart admonition\">\n<p class=\"admonition-title\">Le serveur de développement ne va pas redémarrer automatiquement</p>\n<p>Après avoir ajouté le module <code class=\"docutils literal notranslate\"><span class=\"pre\">templatetags</span></code>, vous devez redémarrer le serveur avant de pouvoir utiliser les balises ou les filtres dans les gabarits.</p>\n</aside>\n<p>Vos balises et filtres personnalisés se trouveront dans un module à l’intérieur du répertoire <code class=\"docutils literal notranslate\"><span class=\"pre\">templatetags</span></code>. Le nom du fichier de module est le nom que vous utiliserez plus tard pour charger les balises, prenez donc soin de choisir un nom qui n’est pas déjà utilisé pour des balises et filtres d’une autre application.</p>\n<p>Par exemple, si vos balises/filtres personnalisés se trouvent dans un fichier nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">poll_extras.py</span></code>, la disposition des fichiers de votre application pourrait ressembler à 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=\"n\">polls</span><span class=\"o\">/</span>\n    <span class=\"fm\">__init__</span><span class=\"o\">.</span><span class=\"n\">py</span>\n    <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">py</span>\n    <span class=\"n\">templatetags</span><span class=\"o\">/</span>\n        <span class=\"fm\">__init__</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">poll_extras</span><span class=\"o\">.</span><span class=\"n\">py</span>\n    <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">py</span>\n</code></pre></div>\n<p>Et dans votre gabarit, voici ce qu’il faudrait écrire :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">load</span> <span class=\"nv\">poll_extras</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>L’application qui contient les balises personnalisées doit apparaître dans <a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> pour que la balise <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">load</span> <span class=\"pre\">%}</span></code></a> fonctionne. C’est un élément de sécurité : cela permet d’accueillir du code Python de beaucoup de bibliothèques de gabarits sur une même machine sans devoir permettre l’accès à toutes ces bibliothèques pour chaque installation Django.</p>\n<p>Il n’y a aucune limite sur le nombre de modules que l’on peut placer dans le paquet <code class=\"docutils literal notranslate\"><span class=\"pre\">templatetags</span></code>. Gardez simplement à l’esprit qu’une commande <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">load</span> <span class=\"pre\">%}</span></code></a> va charger les balises/filtres du nom de module Python indiqué, et non pas du nom de l’application.</p>\n<p>Pour être valide, le module de la bibliothèque de balises doit contenir une variable au niveau module nommée <code class=\"docutils literal notranslate\"><span class=\"pre\">register</span></code> et qui doit être une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">template.Library</span></code>, dans laquelle toutes les balises et les filtres sont inscrits. Ainsi, dans la partie supérieure de votre module, écrivez 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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"n\">register</span> <span class=\"o\">=</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Library</span><span class=\"p\">()</span>\n</code></pre></div>\n<aside class=\"version-note version-added\" data-version=\"1.9\">\n<p class=\"version-note-title\">New in Django 1.9</p></aside>\n<p>Il est aussi possible d’inscrire les modules de balises de gabarit au moyen du paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">'libraries'</span></code> de <a class=\"reference internal\" href=\"/fr/1.9/topics/templates/#django.template.backends.django.DjangoTemplates\" title=\"django.template.backends.django.DjangoTemplates\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code></a>. Cette méthode est utile si vous souhaitez utiliser un nom autre que celui du module de balises de gabarit au moment de charger ces balises. Cela permet aussi d’inscrire des balises sans devoir installer une application.</p>\n<aside class=\"admonition-behind-the-scenes admonition\">\n<p class=\"admonition-title\">En coulisses</p>\n<p>Pour de multiples exemples, lisez le code source des filtres et balises par défaut de Django. Vous les trouverez respectivement dans <code class=\"docutils literal notranslate\"><span class=\"pre\">django/template/defaultfilters.py</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">django/template/defaulttags.py</span></code>.</p>\n<p>Pour plus d’informations sur la balise <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">load</span></code></a>, lisez sa documentation.</p>\n</aside>\n</section>\n<section id=\"writing-custom-template-filters\">\n<span id=\"howto-writing-custom-template-filters\"></span><h2>Écriture de filtres de gabarits personnalisés<a class=\"heading-anchor\" href=\"#writing-custom-template-filters\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Les filtres personnalisés ne sont que des fonctions Python qui acceptent un ou deux paramètres :</p>\n<ul class=\"simple\">\n<li><p>La valeur de la variable (en entrée), pas forcément une chaîne.</p></li>\n<li><p>La valeur du paramètre ; il peut avoir une valeur par défaut ou être simplement absent.</p></li>\n</ul>\n<p>Par exemple, dans le filtre <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">var|foo:&quot;bar&quot;</span> <span class=\"pre\">}}</span></code>, le filtre <code class=\"docutils literal notranslate\"><span class=\"pre\">foo</span></code> reçoit la variable <code class=\"docutils literal notranslate\"><span class=\"pre\">var</span></code> et le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;bar&quot;</span></code>.</p>\n<p>Dans la mesure où le langage de gabarit ne s’occupe pas de la gestion des exceptions, toute exception générée dans un filtre de gabarit apparaît comme erreur de serveur. C’est pourquoi les fonctions de filtres devraient éviter de générer des exceptions quand il existe une valeur de repli raisonnable à renvoyer. Dans le cas d’une valeur d’entrée représentant clairement un bogue dans un gabarit, il se peut que la génération d’une exception soit toujours la meilleure solution plutôt que d’échouer silencieusement en masquant l’erreur.</p>\n<p>Voici un exemple de définition de filtre :</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">cut</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">arg</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;Removes all values of arg from the given string&quot;&quot;&quot;</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">replace</span><span class=\"p\">(</span><span class=\"n\">arg</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Et voici une exemple de la manière dont ce filtre pourrait être utilisé :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{{</span> <span class=\"nv\">somevariable</span><span class=\"o\">|</span><span class=\"nf\">cut</span><span class=\"s2\">:&quot;0&quot;</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n<p>La plupart des filtres n’acceptent pas de paramètre. Dans ce cas, ne rajoutez pas de paramètre à votre fonction. Exemple :</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">lower</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span> <span class=\"c1\"># Only one argument.</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;Converts a string into all lowercase&quot;&quot;&quot;</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">lower</span><span class=\"p\">()</span>\n</code></pre></div>\n<section id=\"registering-custom-filters\">\n<h3>Inscription de filtres personnalisés<a class=\"heading-anchor\" href=\"#registering-custom-filters\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.filter\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">django.template.Library.</span></span><span class=\"sig-name descname\"><span class=\"pre\">filter</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.filter\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Après avoir écrit la définition d’un filtre, il est nécessaire de l’inscrire avec votre instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">Library</span></code> pour qu’il soit disponible dans le langage de gabarit de Django :</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=\"n\">register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"s1\">&#39;cut&#39;</span><span class=\"p\">,</span> <span class=\"n\">cut</span><span class=\"p\">)</span>\n<span class=\"n\">register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"s1\">&#39;lower&#39;</span><span class=\"p\">,</span> <span class=\"n\">lower</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">Library.filter()</span></code> accepte deux paramètres :</p>\n<ol class=\"arabic simple\">\n<li><p>Le nom du filtre, une chaîne.</p></li>\n<li><p>La fonction de compilation, une fonction Python (et non pas le nom de la fonction sous forme de chaîne).</p></li>\n</ol>\n<p>Vous pouvez aussi utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">register.filter()</span></code> sous forme de décorateur :</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;cut&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">cut</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">arg</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">replace</span><span class=\"p\">(</span><span class=\"n\">arg</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">lower</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">lower</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Si vous omettez le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> comme dans le second exemple ci-dessus, Django utilisera le nom de la fonction comme nom de filtre.</p>\n<p>Pour terminer, <code class=\"docutils literal notranslate\"><span class=\"pre\">register.filter()</span></code> accepte aussi trois paramètres nommés : <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">needs_autoescape</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">expects_localtime</span></code>. Ces paramètres sont décrits dans <a class=\"reference internal\" href=\"#filters-auto-escaping\"><span class=\"std std-ref\">filtres et échappement automatique</span></a> et <a class=\"reference internal\" href=\"#filters-timezones\"><span class=\"std std-ref\">filtres et fuseaux horaires</span></a> ci-dessous.</p>\n</section>\n<section id=\"template-filters-that-expect-strings\">\n<h3>Filtres de gabarits agissant sur des chaînes<a class=\"heading-anchor\" href=\"#template-filters-that-expect-strings\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.defaultfilters.stringfilter\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">django.template.defaultfilters.</span></span><span class=\"sig-name descname\"><span class=\"pre\">stringfilter</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.defaultfilters.stringfilter\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Si vous écrivez un filtre de gabarit qui s’attend uniquement à une chaîne comme premier paramètre, vous devriez utiliser le décorateur <code class=\"docutils literal notranslate\"><span class=\"pre\">stringfilter</span></code>. Celui-ci se chargera de convertir un objet dans son équivalent chaîne de caractères avant de le passer à votre fonction :</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</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template.defaultfilters</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">stringfilter</span>\n\n<span class=\"n\">register</span> <span class=\"o\">=</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Library</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span>\n<span class=\"nd\">@stringfilter</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">lower</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">lower</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>De cette façon, vous pourrez par exemple passer un nombre entier à ce filtre et il ne générera pas d’erreur <code class=\"docutils literal notranslate\"><span class=\"pre\">AttributeError</span></code> (les nombres entiers n’ont pas de méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">lower()</span></code>).</p>\n</section>\n<section id=\"filters-and-auto-escaping\">\n<span id=\"filters-auto-escaping\"></span><h3>Les filtres et l’échappement automatique<a class=\"heading-anchor\" href=\"#filters-and-auto-escaping\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Quand vous écrivez un filtre personnalisé, réfléchissez sur la façon dont celui-ci va interagir avec le comportement d’échappement automatique de Django. Notez que trois types de chaînes peuvent circuler dans le code des gabarits :</p>\n<ul>\n<li><p>Des <strong>chaînes brutes</strong>, c’est-à-dire de types Python natifs <code class=\"docutils literal notranslate\"><span class=\"pre\">str</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">unicode</span></code>. En sortie, et si l’échappement automatique est en vigueur, ces chaînes seront échappées, sinon elles sont laissées telles quelles.</p></li>\n<li><p>Des <strong>chaînes sûres</strong> sont des chaînes qui ont été marquées comme sûres et par là-même qu’elles n’ont plus besoin d’être échappées au moment de l’affichage. Tout échappement nécessaire aura déjà été effectué. Elles sont habituellement utilisées pour des chaînes qui contiennent du HTML brut devant être interprété tel quel au niveau du client.</p>\n<p>En interne, ces chaînes sont de type <code class=\"docutils literal notranslate\"><span class=\"pre\">SafeBytes</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">SafeText</span></code>. Elles ont en commun la classe de base <code class=\"docutils literal notranslate\"><span class=\"pre\">SafeData</span></code>, ce qui permet de les identifier en utilisant du code comme :</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=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">SafeData</span><span class=\"p\">):</span>\n    <span class=\"c1\"># Do something with the &quot;safe&quot; string.</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</li>\n<li><p><strong>Les chaînes marquées comme ayant besoin d’échappement</strong> sont <em>toujours</em> échappées à l’affichage, qu’elles soient dans un bloc <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-autoescape\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">autoescape</span></code></a> ou non. Ces chaînes sont échappées une seule fois, même si l’échappement automatique est actif.</p>\n<p>En interne, ces chaînes sont de type <code class=\"docutils literal notranslate\"><span class=\"pre\">EscapeBytes</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">EscapeText</span></code>. Vous n’avez généralement pas à vous soucier d’elles ; elles existent en vue de l’implémentation du filtre <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatefilter-escape\"><code class=\"xref std std-tfilter docutils literal notranslate\"><span class=\"pre\">escape</span></code></a>.</p>\n</li>\n</ul>\n<p>Le code des filtres de gabarits entre dans l’une des deux situations suivantes :</p>\n<ol class=\"arabic\">\n<li><p>Votre filtre n’introduit aucun nouveau caractère HTML non sûr (<code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">&gt;</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">&amp;</span></code>) dans le résultat. Dans ce cas, vous pouvez laisser Django s’occuper de toute la gestion de l’échappement automatique. Tout ce que vous avez à faire est de définir le drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> lorsque vous inscrivez votre fonction de filtre, comme 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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">is_safe</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">myfilter</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span>\n</code></pre></div>\n<p>Ce drapeau indique à Django que si une chaîne « sûre » (safe) est passée à votre filtre, le résultat sera toujours « sûr » et que si une chaîne non sûre est passée, Django l’échappera automatiquement si nécessaire.</p>\n<p>Vous pouvez considérer cela comme signifiant que « ce filtre est sûr, il n’introduit aucune éventualité de code HTML non sûr ».</p>\n<p>La raison d’être de <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> est qu’il existe un grand nombre d’opérations normales sur les chaînes qui transforment un objet <code class=\"docutils literal notranslate\"><span class=\"pre\">SafeData</span></code> en un objet <code class=\"docutils literal notranslate\"><span class=\"pre\">str</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">unicode</span></code> normal, et qu’au lieu d’essayer d’identifier tous ces cas de figure, ce qui serait très difficile, Django répare les dommages après que le filtre ait fait son travail.</p>\n<p>Par exemple, imaginons un filtre qui ajoute la chaîne <code class=\"docutils literal notranslate\"><span class=\"pre\">xx</span></code> à la fin de n’importe quelle variable d’entrée. Comme cela n’introduit aucun caractère HTML dangereux dans le résultat (sauf s’il y en avait déjà), vous devriez marquer ce filtre avec <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">is_safe</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">add_xx</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\">xx&#39;</span> <span class=\"o\">%</span> <span class=\"n\">value</span>\n</code></pre></div>\n<p>Lorsque ce filtre est utilisé dans un gabarit dans lequel l’échappement automatique est en vigueur, Django va échapper le contenu chaque fois que la variable dde départ n’est pas déjà marquée comme « sûre ».</p>\n<p>Par défaut, <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>, et vous pouvez simplement l’omettre quand il n’est pas nécessaire.</p>\n<p>Soyez prudent quand vous décidez si votre filtre conserve réellement des chaînes sûres. Si vous <em>enlevez</em> des caractères, il se peut que vous laissiez par mégarde des balises ou entités HTML mal équilibrées dans le résultat. Par exemple, en enlevant un <code class=\"docutils literal notranslate\"><span class=\"pre\">&gt;</span></code> du contenu initial, cela pourrait transformer <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;a&gt;</span></code> en <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;a</span></code> qui devrait alors être échappé à l’affichage pour éviter de poser des problèmes. De même, enlever un point-virgule (<code class=\"docutils literal notranslate\"><span class=\"pre\">;</span></code>) peut transformer <code class=\"docutils literal notranslate\"><span class=\"pre\">&amp;amp;</span></code> en <code class=\"docutils literal notranslate\"><span class=\"pre\">&amp;amp</span></code>, ce qui n’est plus une entité valide et devrait donc de nouveau être échappé. Ce ne sera pas si subtil dans la plupart des cas, mais gardez à l’esprit ce genre de problème potentiel lorsque vous relisez votre code.</p>\n<p>Le marquage d’un filtre avec <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> force la valeur de retour du filtre en chaîne de caractères. Si votre filtre doit renvoyer un booléen ou une autre valeur non textuelle, le marquage avec <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> va probablement générer des conséquences inattendues (comme la conversion du booléen False en chaîne “False”).</p>\n</li>\n<li><p>Une autre option possible est de s’occuper manuellement dans le code du filtre d’effectuer d’éventuels échappements. C’est nécessaire quand vous introduisez de nouvelles balises HTML dans le résultat. Il faut alors marquer le contenu comme sûr et exempt de besoin d’échappement afin que le code HTML introduit ne soit pas échappé plus tard, ce qui implique donc que vous gériez vous-même ce contenu.</p>\n<p>Pour marquer le résultat comme une chaîne sûre, utilisez <a class=\"reference internal\" href=\"/fr/1.9/ref/utils/#django.utils.safestring.mark_safe\" title=\"django.utils.safestring.mark_safe\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">django.utils.safestring.mark_safe()</span></code></a>.</p>\n<p>Mais restez prudent. Vous devez faire plus que simplement marquer le résultat comme sûr. Vous devez vous assurer qu’il soit <em>réellement</em> sûr et votre action dépend de l’activité de l’échappement automatique. L’idée est d’écrire des filtres qui peuvent agir dans des gabarits où l’échappement automatique est activé ou non, afin de faciliter la tâche aux rédacteurs de gabarits.</p>\n<p>Pour que vos filtres sachent si l’échappement automatique est actuellement actif, définissez le drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">needs_autoescape</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> lorsque vous inscrivez votre fonction de filtre (il vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> par défaut). Ce drapeau indique à Django que votre fonction de filtre souhaite recevoir un paramètre mot-clé supplémentaire, <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape</span></code>. Ce paramètre vaudra <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> quand l’échappement automatique est en vigueur et <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> dans le cas contraire. Il est recommandé de définir la valeur par défaut du paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, pour que si la fonction est appelée depuis le code Python, l’échappement soit activé par défaut.</p>\n<p>Par exemple, écrivons un filtre qui met en évidence le premier caractère d’une chaîne :</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</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils.html</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">conditional_escape</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils.safestring</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">mark_safe</span>\n\n<span class=\"n\">register</span> <span class=\"o\">=</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Library</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">needs_autoescape</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">initial_letter_filter</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">,</span> <span class=\"n\">autoescape</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">):</span>\n    <span class=\"n\">first</span><span class=\"p\">,</span> <span class=\"n\">other</span> <span class=\"o\">=</span> <span class=\"n\">text</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">],</span> <span class=\"n\">text</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:]</span>\n    <span class=\"k\">if</span> <span class=\"n\">autoescape</span><span class=\"p\">:</span>\n        <span class=\"n\">esc</span> <span class=\"o\">=</span> <span class=\"n\">conditional_escape</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"n\">esc</span> <span class=\"o\">=</span> <span class=\"k\">lambda</span> <span class=\"n\">x</span><span class=\"p\">:</span> <span class=\"n\">x</span>\n    <span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;&lt;strong&gt;</span><span class=\"si\">%s</span><span class=\"s1\">&lt;/strong&gt;</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">esc</span><span class=\"p\">(</span><span class=\"n\">first</span><span class=\"p\">),</span> <span class=\"n\">esc</span><span class=\"p\">(</span><span class=\"n\">other</span><span class=\"p\">))</span>\n    <span class=\"k\">return</span> <span class=\"n\">mark_safe</span><span class=\"p\">(</span><span class=\"n\">result</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Le drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">needs_autoescape</span></code> et le paramètre nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape</span></code> signifient que notre fonction saura si l’échappement automatique est en vigueur au moment où le filtre est appelé. Nous utilisons <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape</span></code> pour savoir si nous devons faire passer les données reçues par la fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">django.utils.html.conditional_escape</span></code> (sinon, nous utilisons la fonction neutre comme fonction d’échappement). La fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">conditional_escape()</span></code> est semblable à <code class=\"docutils literal notranslate\"><span class=\"pre\">escape()</span></code>, sauf que l’échappement n’a lieu que si la valeur d’entrée n’est <strong>pas</strong> déjà une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">SafeData</span></code>. Si une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">SafeData</span></code> est transmise à <code class=\"docutils literal notranslate\"><span class=\"pre\">conditional_escape()</span></code>, les données sont renvoyées sans être modifiées.</p>\n<p>Finalement, dans l’exemple ci-dessus, nous n’oublions pas de marquer le résultat comme sûr afin que notre code HTML soit inséré directement dans le gabarit sans échappement supplémentaire.</p>\n<p>Il n’y a pas besoin de se préoccuper du drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> dans ce cas (même si on pourrait le définir sans dommages). Chaque fois que vous gérez manuellement la question de l’échappement automatique et que vous renvoyez une chaîne sûre, le drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">is_safe</span></code> ne change rien, quelle que soit sa valeur.</p>\n</li>\n</ol>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Risque de vulnérabilités XSS lors de la réutilisation de filtres intégrés</p>\n<aside class=\"version-note version-changed\" data-version=\"1.8\">\n<p class=\"version-note-title\">Changed in Django 1.8</p></aside>\n<p>Les filtres intégrés de Django contiennent <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape=True</span></code> par défaut afin d’obtenir le bon comportement d’échappement automatique et d’éviter ainsi une éventuelle vulnérabilité de script inter-site.</p>\n<p>Dans les versions plus anciennes de Django, réutilisez prudemment les filtres intégrés de Django car la valeur par défaut de <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape</span></code> est <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>. Vous devrez passer explicitement <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape=True</span></code> pour que le résultat soit automatiquement échappé.</p>\n<p>Par exemple, si vous voulez écrire un filtre personnalisé nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">urlize_and_linebreaks</span></code> qui combine les filtres <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatefilter-urlize\"><code class=\"xref std std-tfilter docutils literal notranslate\"><span class=\"pre\">urlize</span></code></a> et <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatefilter-linebreaksbr\"><code class=\"xref std std-tfilter docutils literal notranslate\"><span class=\"pre\">linebreaksbr</span></code></a>, le filtre pourrait ressembler à 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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template.defaultfilters</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">linebreaksbr</span><span class=\"p\">,</span> <span class=\"n\">urlize</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">needs_autoescape</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">urlize_and_linebreaks</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">,</span> <span class=\"n\">autoescape</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">linebreaksbr</span><span class=\"p\">(</span>\n        <span class=\"n\">urlize</span><span class=\"p\">(</span><span class=\"n\">text</span><span class=\"p\">,</span> <span class=\"n\">autoescape</span><span class=\"o\">=</span><span class=\"n\">autoescape</span><span class=\"p\">),</span>\n        <span class=\"n\">autoescape</span><span class=\"o\">=</span><span class=\"n\">autoescape</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>Puis :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{{</span> <span class=\"nv\">comment</span><span class=\"o\">|</span><span class=\"nf\">urlize_and_linebreaks</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n<p>serait équivalent à :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{{</span> <span class=\"nv\">comment</span><span class=\"o\">|</span><span class=\"nf\">urlize</span><span class=\"o\">|</span><span class=\"nf\">linebreaksbr</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"filters-and-time-zones\">\n<span id=\"filters-timezones\"></span><h3>Filtres et fuseaux horaires<a class=\"heading-anchor\" href=\"#filters-and-time-zones\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous écrivez un filtre personnalisé qui opère sur des objets <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.datetime\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">datetime</span></code></a>, vous allez généralement l’inscrire avec le drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">expects_localtime</span></code> défini à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">expects_localtime</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">businesshours</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"mi\">9</span> <span class=\"o\">&lt;=</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">hour</span> <span class=\"o\">&lt;</span> <span class=\"mi\">17</span>\n    <span class=\"k\">except</span> <span class=\"ne\">AttributeError</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<p>Lorsque ce drapeau est défini et si le premier paramètre du filtre est un objet date/heure sensible aux fuseaux horaires, Django le convertit au besoin dans le fuseau horaire actuel avant de le passer à votre filtre, selon les <a class=\"reference internal\" href=\"/fr/1.9/topics/i18n/timezones/#time-zones-in-templates\"><span class=\"std std-ref\">règles de conversion de fuseaux horaires dans les gabarits</span></a>.</p>\n</section>\n</section>\n<section id=\"writing-custom-template-tags\">\n<span id=\"howto-writing-custom-template-tags\"></span><h2>Écriture de balises de gabarits personnalisées<a class=\"heading-anchor\" href=\"#writing-custom-template-tags\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Les balises sont plus complexes que les filtres, car les balises peuvent tout faire. Django fournit un certain nombre de raccourcis qui facilitent l’écriture de la plupart des types de balises. Nous allons commencer par explorer ces raccourcis, puis expliquer comment écrire une balise à partir de rien pour les cas où les raccourcis ne conviennent pas au besoin.</p>\n<section id=\"simple-tags\">\n<span id=\"howto-custom-template-tags-simple-tags\"></span><h3>Balises simples<a class=\"heading-anchor\" href=\"#simple-tags\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.simple_tag\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">django.template.Library.</span></span><span class=\"sig-name descname\"><span class=\"pre\">simple_tag</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.simple_tag\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Bien des balises de gabarit acceptent des paramètres (chaînes ou variables de gabarit) et renvoient un résultat après avoir effectué quelques opérations sur la base des paramètres initiaux et de certaines informations externes. Par exemple, une balise <code class=\"docutils literal notranslate\"><span class=\"pre\">current_time</span></code> pourrait accepter une chaîne de formatage et renvoyer l’heure sous forme de chaîne dans le bon format.</p>\n<p>Pour faciliter la création de ce type de balise, Django fournit une fonction utilitaire, <code class=\"docutils literal notranslate\"><span class=\"pre\">simple_tag</span></code>. Cette fonction, qui est une méthode de <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.Library</span></code>, accepte elle-même une fonction qui accepte autant de paramètres que nécessaire, l’enveloppe dans une fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">render</span></code> ainsi que les autres éléments nécessaires tels que mentionnés ci-dessus et l’inscrit dans le système de gabarits.</p>\n<p>Notre fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">current_time</span></code> pourrait donc être écrite comme 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=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"n\">register</span> <span class=\"o\">=</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Library</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">simple_tag</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">current_time</span><span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Quelques petites choses à signaler au sujet de la fonction utilitaire <code class=\"docutils literal notranslate\"><span class=\"pre\">simple_tag</span></code>:</p>\n<ul class=\"simple\">\n<li><p>Le contrôle du nombre de paramètres requis, etc., a déjà été effectué au moment où notre fonction est appelée, nous n’avons donc pas à le faire.</p></li>\n<li><p>Les guillemets autour du paramètre (le cas échéant) ont déjà été enlevés, nous recevons donc une chaîne normale.</p></li>\n<li><p>Si le paramètre était une variable de gabarit, notre fonction reçoit la valeur réelle de la variable et non pas la variable elle-même.</p></li>\n</ul>\n<p>Au contraire des autres utilitaires de balises, <code class=\"docutils literal notranslate\"><span class=\"pre\">simple_tag</span></code> passe son résultat par <a class=\"reference internal\" href=\"/fr/1.9/ref/utils/#django.utils.html.conditional_escape\" title=\"django.utils.html.conditional_escape\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">conditional_escape()</span></code></a> si le contexte de gabarit est en mode échappement automatique, pour garantir du HTML correct et vous protéger d’éventuelles vulnérabilités XSS.</p>\n<p>Si l’échappement complémentaire n’est pas souhaité, il est nécessaire d’utiliser <a class=\"reference internal\" href=\"/fr/1.9/ref/utils/#django.utils.safestring.mark_safe\" title=\"django.utils.safestring.mark_safe\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">mark_safe()</span></code></a> pour autant que vous soyez absolument sûr que votre code ne contienne pas de vulnérabilité XSS. Pour la construction de petits bouts de HTML, il est fortement recommandé d’utiliser <a class=\"reference internal\" href=\"/fr/1.9/ref/utils/#django.utils.html.format_html\" title=\"django.utils.html.format_html\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">format_html()</span></code></a> au lieu de <code class=\"docutils literal notranslate\"><span class=\"pre\">mark_safe()</span></code>.</p>\n<aside class=\"version-note version-changed\" data-version=\"1.9\">\n<p class=\"version-note-title\">Changed in Django 1.9</p><p>L’échappement automatique pour <code class=\"docutils literal notranslate\"><span class=\"pre\">simple_tag</span></code> tel que décrit dans les deux paragraphes précédents a été ajouté.</p>\n</aside>\n<p>Si votre balise de gabarit a besoin d’accéder au contexte en cours, vous pouvez utiliser le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context</span></code> lors de l’inscription de la balise :</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">simple_tag</span><span class=\"p\">(</span><span class=\"n\">takes_context</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">current_time</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"n\">format_string</span><span class=\"p\">):</span>\n    <span class=\"n\">timezone</span> <span class=\"o\">=</span> <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;timezone&#39;</span><span class=\"p\">]</span>\n    <span class=\"k\">return</span> <span class=\"n\">your_get_current_time_method</span><span class=\"p\">(</span><span class=\"n\">timezone</span><span class=\"p\">,</span> <span class=\"n\">format_string</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Notez que le premier paramètre <em>doit</em> être nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code>.</p>\n<p>Pour plus d’informations sur le fonctionnement de l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context</span></code>, consultez la section sur les <a class=\"reference internal\" href=\"#howto-custom-template-tags-inclusion-tags\"><span class=\"std std-ref\">balises d’inclusion</span></a>.</p>\n<p>Si vous avez besoin de renommer votre balise, vous pouvez lui donner un nom personnalisé :</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=\"n\">register</span><span class=\"o\">.</span><span class=\"n\">simple_tag</span><span class=\"p\">(</span><span class=\"k\">lambda</span> <span class=\"n\">x</span><span class=\"p\">:</span> <span class=\"n\">x</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;minusone&#39;</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">simple_tag</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;minustwo&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">some_function</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span> <span class=\"o\">-</span> <span class=\"mi\">2</span>\n</code></pre></div>\n<p>Les fonctions <code class=\"docutils literal notranslate\"><span class=\"pre\">simple_tag</span></code> peuvent accepter n’importe quel nombre de paramètres positionnels ou nommés. Par exemple :</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">simple_tag</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_tag</span><span class=\"p\">(</span><span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"n\">warning</span> <span class=\"o\">=</span> <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;warning&#39;</span><span class=\"p\">]</span>\n    <span class=\"n\">profile</span> <span class=\"o\">=</span> <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;profile&#39;</span><span class=\"p\">]</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">return</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>Puis, dans le gabarit, n’importe quel nombre de paramètres séparés par des espaces peuvent être transmis à la balise de gabarit. Comme en Python, les valeurs des paramètres nommés sont définis par le signe égal (<code class=\"docutils literal notranslate\"><span class=\"pre\">=</span></code>) et doivent être placés après les paramètres positionnels. Par exemple :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">my_tag</span> <span class=\"m\">123</span> <span class=\"s2\">&quot;abcd&quot;</span> <span class=\"nv\">book.title</span> <span class=\"nv\">warning</span><span class=\"o\">=</span><span class=\"nv\">message</span><span class=\"o\">|</span><span class=\"nf\">lower</span> <span class=\"nv\">profile</span><span class=\"o\">=</span><span class=\"nv\">user.profile</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<aside class=\"version-note version-added\" data-version=\"1.9\">\n<p class=\"version-note-title\">New in Django 1.9</p></aside>\n<p>Il est possible de stocker le résultat de la balise dans une variable de gabarit au lieu de l’afficher directement. Cela se fait en utilisant le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">as</span></code> suivi du nom de variable. Ce faisant, vous pouvez ensuite afficher ce contenu à l’endroit où vous le souhaitez :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">the_time</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{{</span> <span class=\"nv\">the_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"inclusion-tags\">\n<span id=\"howto-custom-template-tags-inclusion-tags\"></span><h3>Balises d’inclusion<a class=\"heading-anchor\" href=\"#inclusion-tags\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.inclusion_tag\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">django.template.Library.</span></span><span class=\"sig-name descname\"><span class=\"pre\">inclusion_tag</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.inclusion_tag\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Un autre type de balises de gabarit fréquent est le type qui affiche certaines données en effectuant le rendu d’un <em>autre</em> gabarit. Par exemple, l’interface d’administration de Django utilise des balises de gabarit personnalisées pour afficher les boutons au bas des pages de formulaires d’ajout/édition. Ces boutons ont toujours une même apparence, mais les cibles de leurs liens changent en fonction de l’objet en cours d’édition, ils représentent donc un cas typique d’utilisation d’un petit gabarit complété par certains détails sur l’objet en cours (dans le cas précis de l’interface d’administration, il s’agit de la balise <code class=\"docutils literal notranslate\"><span class=\"pre\">submit_row</span></code>).</p>\n<p>Ces types de balises sont appelées des « balises d’inclusion ».</p>\n<p>Un exemple sera le meilleur moyen d’illustrer l’écriture de balises d’inclusion. Écrivons une balise qui affiche une liste de choix pour un objet  <code class=\"docutils literal notranslate\"><span class=\"pre\">Poll</span></code> donné, comme celui qui a été créé dans les <a class=\"reference internal\" href=\"/fr/1.9/intro/tutorial02/#creating-models\"><span class=\"std std-ref\">tutoriels</span></a>. Nous utiliserons la balise comme ceci :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">show_results</span> <span class=\"nv\">poll</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>… et cela donnera le résultat suivant :</p>\n<div class=\"code-block\" data-language=\"html\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Html</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=\"Html code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>First choice<span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>Second choice<span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>Third choice<span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Pour commencer, définissez la fonction qui accepte le paramètre et qui produit un dictionnaire de données comme résultat. Le point important ici est que nous devons uniquement renvoyer un dictionnaire, rien d’autre de plus complexe. Il sera utilisé comme contexte de gabarit pour le fragment de gabarit. Exemple :</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">show_results</span><span class=\"p\">(</span><span class=\"n\">poll</span><span class=\"p\">):</span>\n    <span class=\"n\">choices</span> <span class=\"o\">=</span> <span class=\"n\">poll</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n    <span class=\"k\">return</span> <span class=\"p\">{</span><span class=\"s1\">&#39;choices&#39;</span><span class=\"p\">:</span> <span class=\"n\">choices</span><span class=\"p\">}</span>\n</code></pre></div>\n<p>Ensuite, créez le gabarit utilisé pour faire le rendu du résultat de la balise. Ce gabarit est une fonctionnalité figée de la balise : c’est le rédacteur de la balise qui le définit, pas le concepteur des gabarits. Suivant notre exemple, le gabarit est très simple :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">choice</span> <span class=\"k\">in</span> <span class=\"nv\">choices</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span> <span class=\"cp\">{{</span> <span class=\"nv\">choice</span> <span class=\"cp\">}}</span> <span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Maintenant, créez et inscrivez la balise d’inclusion en appelant la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">inclusion_tag()</span></code> d’un objet <code class=\"docutils literal notranslate\"><span class=\"pre\">Library</span></code>. Suivant notre exemple, si le gabarit ci-dessus se trouve dans un fichier nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">results.html</span></code> dans un répertoire parcouru par le chargeur de gabarits, voici comment nous inscrivons la balise :</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=\"c1\"># Here, register is a django.template.Library instance, as before</span>\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">inclusion_tag</span><span class=\"p\">(</span><span class=\"s1\">&#39;results.html&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">show_results</span><span class=\"p\">(</span><span class=\"n\">poll</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Il est également possible d’inscrire la balise d’inclusion en utilisant une instance de <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/api/#django.template.Template\" title=\"django.template.Template\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.template.Template</span></code></a>:</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.loader</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">get_template</span>\n<span class=\"n\">t</span> <span class=\"o\">=</span> <span class=\"n\">get_template</span><span class=\"p\">(</span><span class=\"s1\">&#39;results.html&#39;</span><span class=\"p\">)</span>\n<span class=\"n\">register</span><span class=\"o\">.</span><span class=\"n\">inclusion_tag</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">)(</span><span class=\"n\">show_results</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>… lorsque nous avons initialement créé la fonction.</p>\n<p>Il peut arriver que vos balises d’inclusion nécessitent un grand nombre de paramètres, ce qui rend pénible pour les auteurs des gabarits la transmission de tous les paramètres en se souvenant de l’ordre exigé. Pour résoudre ce problème, Django fournit l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context</span></code> pour les balises d’inclusion. Si vous définissez <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context</span></code> lors de la création d’une balise de gabarit, celle-ci n’aura aucun paramètre obligatoire et la fonction Python sous-jacente recevra un paramètre, le contexte du gabarit au moment où la balise a été appelée.</p>\n<p>Par exemple, disons que vous écrivez une balise d’inclusion qui sera toujours utilisée dans un contexte contenant les variables <code class=\"docutils literal notranslate\"><span class=\"pre\">home_link</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">home_title</span></code> pointant sur la page principale. Voici à quoi la fonction Python ressemblerait :</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">inclusion_tag</span><span class=\"p\">(</span><span class=\"s1\">&#39;link.html&#39;</span><span class=\"p\">,</span> <span class=\"n\">takes_context</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">jump_link</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;link&#39;</span><span class=\"p\">:</span> <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;home_link&#39;</span><span class=\"p\">],</span>\n        <span class=\"s1\">&#39;title&#39;</span><span class=\"p\">:</span> <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;home_title&#39;</span><span class=\"p\">],</span>\n    <span class=\"p\">}</span>\n</code></pre></div>\n<p>Notez que le premier paramètre de la fonction <em>doit</em> être nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code>.</p>\n<p>Dans la ligne <code class=\"docutils literal notranslate\"><span class=\"pre\">register.inclusion_tag()</span></code>, nous précisons <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context=True</span></code> ainsi que le nom du gabarit. Voici à quoi pourrait ressembler le gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">link.html</span></code>:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code>Jump directly to <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">link</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">title</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>.\n</code></pre></div>\n<p>Puis, chaque fois que vous souhaitez utiliser cette balise personnalisée, chargez sa bibliothèque et appelez-la sans paramètre, comme ceci :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">jump_link</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Notez que lorsque vous utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context=True</span></code>, il n’y a pas besoin de transmettre de paramètres à la balise de gabarit. Cette dernière a automatiquement accès au contexte.</p>\n<p>Le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context</span></code> vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> par défaut. Lorsqu’il est défini à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, la balise reçoit l’objet contexte, comme dans cet exemple. C’est la seule différence entre ce cas et l’exemple <code class=\"docutils literal notranslate\"><span class=\"pre\">inclusion_tag</span></code> précédent.</p>\n<p>Les fonctions <code class=\"docutils literal notranslate\"><span class=\"pre\">inclusion_tag</span></code> acceptent n’importe quel nombre de paramètres positionnels ou nommés. Par exemple :</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">inclusion_tag</span><span class=\"p\">(</span><span class=\"s1\">&#39;my_template.html&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_tag</span><span class=\"p\">(</span><span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"n\">warning</span> <span class=\"o\">=</span> <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;warning&#39;</span><span class=\"p\">]</span>\n    <span class=\"n\">profile</span> <span class=\"o\">=</span> <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;profile&#39;</span><span class=\"p\">]</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">return</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>Puis, dans le gabarit, n’importe quel nombre de paramètres séparés par des espaces peuvent être transmis à la balise de gabarit. Comme en Python, les valeurs des paramètres nommés sont définis par le signe égal (<code class=\"docutils literal notranslate\"><span class=\"pre\">=</span></code>) et doivent être placés après les paramètres positionnels. Par exemple :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">my_tag</span> <span class=\"m\">123</span> <span class=\"s2\">&quot;abcd&quot;</span> <span class=\"nv\">book.title</span> <span class=\"nv\">warning</span><span class=\"o\">=</span><span class=\"nv\">message</span><span class=\"o\">|</span><span class=\"nf\">lower</span> <span class=\"nv\">profile</span><span class=\"o\">=</span><span class=\"nv\">user.profile</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n<section id=\"assignment-tags\">\n<h3>Balises d’attribution<a class=\"heading-anchor\" href=\"#assignment-tags\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.assignment_tag\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">django.template.Library.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assignment_tag</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.assignment_tag\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<aside class=\"version-note version-deprecated\" data-version=\"1.9\">\n<p class=\"version-note-title\">Deprecated since Django 1.9</p><p><span class=\"versionmodified deprecated\">Obsolète depuis la version 1.9: </span><code class=\"docutils literal notranslate\"><span class=\"pre\">simple_tag</span></code> est dorénavant capable de stocker son résultat dans une variable de gabarit et devrait être privilégié.</p>\n</aside>\n<p>Pour faciliter la création de balises définissant une variable dans le contexte, Django fournit la fonction utilitaire <code class=\"docutils literal notranslate\"><span class=\"pre\">assignment_tag</span></code>. Cette fonction fonctionne de la même manière que <a class=\"reference internal\" href=\"#django.template.Library.simple_tag\" title=\"django.template.Library.simple_tag\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">simple_tag()</span></code></a>, sauf qu’elle stocke le résultat de la balise dans la variable de contexte indiquée plutôt que de directement l’afficher.</p>\n<p>Notre fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">current_time</span></code> précédente aurait donc pu être écrite comme 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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">assignment_tag</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_current_time</span><span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Vous pouvez ensuite stocker le résultat dans une variable de gabarit en utilisant le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">as</span></code> suivi du nom de variable, et l’afficher vous-même là où vous le souhaitez :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">get_current_time</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">the_time</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{{</span> <span class=\"nv\">the_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"advanced-custom-template-tags\">\n<h3>Balises de gabarits personnalisées (niveau avancé)<a class=\"heading-anchor\" href=\"#advanced-custom-template-tags\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il peut arriver que les fonctionnalités de base de la création d’une balise de gabarit personnalisée ne suffisent pas. Ne vous en faites pas. Django vous offre un accès complet à l’interface interne nécessaire pour construire une balise de gabarit à partir de rien.</p>\n</section>\n<section id=\"a-quick-overview\">\n<h3>Aperçu rapide<a class=\"heading-anchor\" href=\"#a-quick-overview\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le système de gabarits fonctionne par un processus en deux étapes : la compilation et le rendu. Pour créer une balise de gabarit personnalisée, il s’agit de définir à la fois le comportement de la compilation et celui du rendu.</p>\n<p>Quand Django compile un gabarit, il divise le texte brut du gabarit en « nœuds ». Chaque nœud est une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.Node</span></code> et possède une méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code>. Un gabarit compilé est simplement une liste d’objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code>. Lorsque vous appelez <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> sur un objet gabarit compilé, le gabarit appelle <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> pour chaque <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> de sa liste de nœuds en leur passant le contexte. Les résultats sont tous concaténés pour former le rendu du gabarit.</p>\n<p>Ainsi, pour créer une balise de gabarit personnalisée, vous définissez la manière de convertir la balise de gabarit brute en un <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> (fonction de compilation) et ce que fait la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> du nœud.</p>\n</section>\n<section id=\"writing-the-compilation-function\">\n<h3>Écriture de la fonction de compilation<a class=\"heading-anchor\" href=\"#writing-the-compilation-function\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour chaque balise de gabarit que l’analyseur de gabarit rencontre, il appelle une fonction Python avec le contenu de la balise et l’objet analyseur lui-même. Cette fonction est responsable de renvoyer une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> en fonction du contenu de la balise.</p>\n<p>Par exemple, écrivons une implémentation complète de notre simple balise de gabarit, <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">current_time</span> <span class=\"pre\">%}</span></code>, qui affiche l’heure et la date courantes formatées en fonction d’un paramètre donné à la balise, en respectant la syntaxe <a class=\"reference external\" href=\"https://docs.python.org/3/library/time.html#time.strftime\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">strftime()</span></code></a>. Il est conseillé de définir la syntaxe de la balise avant toute autre chose. Dans notre cas, disons que la balise devrait être utilisée comme ceci :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"cp\">%}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>L’analyseur de cette fonction doit capturer le paramètre et créer un objet <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</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</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_current_time</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># split_contents() knows not to split quoted strings.</span>\n        <span class=\"n\">tag_name</span><span class=\"p\">,</span> <span class=\"n\">format_string</span> <span class=\"o\">=</span> <span class=\"n\">token</span><span class=\"o\">.</span><span class=\"n\">split_contents</span><span class=\"p\">()</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag requires a single argument&quot;</span> <span class=\"o\">%</span> <span class=\"n\">token</span><span class=\"o\">.</span><span class=\"n\">contents</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"ow\">and</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"s1\">&#39;&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&#39;&quot;</span><span class=\"p\">)):</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag&#39;s argument should be in quotes&quot;</span> <span class=\"o\">%</span> <span class=\"n\">tag_name</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">CurrentTimeNode</span><span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Notes :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parser</span></code> est l’objet analyseur de gabarit. Nous n’en avons pas besoin dans cet exemple.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">token.contents</span></code> est une chaîne formée du contenu brut de la balise. Dans notre exemple, il s’agit de <code class=\"docutils literal notranslate\"><span class=\"pre\">'current_time</span> <span class=\"pre\">&quot;%Y-%m-%d</span> <span class=\"pre\">%I:%M</span> <span class=\"pre\">%p&quot;'</span></code>.</p></li>\n<li><p>La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">token.split_contents()</span></code> sépare les paramètres en fonction des espaces tout en gardant groupées les chaînes entre guillemets. La méthode plus directe <code class=\"docutils literal notranslate\"><span class=\"pre\">token.contents.split()</span></code> ne serait pas aussi robuste, car elle couperait naïvement à <em>chaque</em> espace, y compris ceux à l’intérieur des chaînes entre guillemets. Il est conseillé de toujours utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">token.split_contents()</span></code>.</p></li>\n<li><p>Cette fonction est responsable de lever l’exception <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.TemplateSyntaxError</span></code> à chaque erreur de syntaxe, avec des messages utiles.</p></li>\n<li><p>Les exceptions <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateSyntaxError</span></code> utilisent la variable <code class=\"docutils literal notranslate\"><span class=\"pre\">tag_name</span></code>. Ne codez pas en dur le nom de la balise dans les messages d’erreur, car cela lie le nom de la balise à votre fonction. <code class=\"docutils literal notranslate\"><span class=\"pre\">token.contents.split()[0]</span></code> sera toujours le nom de la balise, même lorsque celle-ci n’accepte aucun paramètre.</p></li>\n<li><p>La fonction renvoie un <code class=\"docutils literal notranslate\"><span class=\"pre\">CurrentTimeNode</span></code> avec tout ce que le nœud a besoin de connaître au sujet de la balise. Dans ce cas, il ne fait que passer le paramètre (<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;%Y-%m-%d</span> <span class=\"pre\">%I:%M</span> <span class=\"pre\">%p&quot;</span></code>). Les guillemets ouvrant et fermant de la balise de gabarit sont enlevés par <code class=\"docutils literal notranslate\"><span class=\"pre\">format_string[1:-1]</span></code>.</p></li>\n<li><p>L’analyse est de très bas niveau. Les développeurs Django ont expérimenté l’écriture de petites infrastructures au-dessus de ce système d’analyse, en utilisant des techniques comme les grammaires EBNF, mais ces expériences ont rendu le moteur de gabarit trop lent. L’analyse est de bas niveau car c’est la solution la plus rapide.</p></li>\n</ul>\n</section>\n<section id=\"writing-the-renderer\">\n<h3>Écriture de la fonction de rendu<a class=\"heading-anchor\" href=\"#writing-the-renderer\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>La seconde étape dans l’écriture de balises de gabarit est définir une sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> possédant une méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code>.</p>\n<p>Pour continuer l’exemple ci-dessus, nous devons définir <code class=\"docutils literal notranslate\"><span class=\"pre\">CurrentTimeNode</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\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CurrentTimeNode</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">format_string</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span> <span class=\"o\">=</span> <span class=\"n\">format_string</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=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Notes :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> reçoit la chaîne <code class=\"docutils literal notranslate\"><span class=\"pre\">format_string</span></code> de <code class=\"docutils literal notranslate\"><span class=\"pre\">do_current_time()</span></code>. Passez toujours toute option ou paramètre à un <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> par l’intermédiaire de sa méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code>.</p></li>\n<li><p>C’est dans la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> que se passe réellement le travail.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> doit généralement échouer silencieusement, particulièrement en environnement de production. Cependant, dans certains cas, spécialement lorsque <code class=\"docutils literal notranslate\"><span class=\"pre\">context.template.engine.debug</span></code> vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, cette méthode peut générer une exception pour faciliter le débogage. Par exemple, plusieurs balises intégrées génèrent <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.TemplateSyntaxError</span></code> si elles reçoivent le mauvais nombre de paramètres ou des paramètres du mauvais type.</p></li>\n</ul>\n<p>Au final, cette distinction entre compilation et rendu aboutit à un système de gabarit efficace, car un gabarit peut produire un rendu avec plusieurs contextes différents sans devoir être analysé plusieurs fois.</p>\n</section>\n<section id=\"auto-escaping-considerations\">\n<span id=\"tags-auto-escaping\"></span><h3>Considérations sur l’échappement automatique<a class=\"heading-anchor\" href=\"#auto-escaping-considerations\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le résultat des balises de gabarit ne passe <strong>pas</strong> automatiquement par les filtres d’échappement automatique (à l’exception de <a class=\"reference internal\" href=\"#django.template.Library.simple_tag\" title=\"django.template.Library.simple_tag\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">simple_tag()</span></code></a> comme expliqué plus haut) . Toutefois, il y a quand même deux ou trois choses à garder à l’esprit en écrivant des balises de gabarit.</p>\n<p>Si la fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> de votre gabarit conserve le résultat dans une variable de contexte (plutôt que de renvoyer le résultat dans une chaîne), elle devrait alors s’occuper d’appeler <code class=\"docutils literal notranslate\"><span class=\"pre\">mark_safe()</span></code> si nécessaire. Lorsque la variable sera finalement affichée, elle sera affectée par le réglage d’échappement automatique en vigueur à ce moment, il faut donc que les contenus qui ne doivent plus être échappés soient marqués comme tels.</p>\n<p>De même, si votre balise de gabarit crée un nouveau contexte pour procéder à certains sous-rendus, définissez l’attribut d’échappement automatique pour la valeur du contexte en cours. La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__</span></code> de la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Context</span></code> accepte un paramètre nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">autoescape</span></code> et qui est destiné à cet effet. Par exemple :</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\">Context</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=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"n\">new_context</span> <span class=\"o\">=</span> <span class=\"n\">Context</span><span class=\"p\">({</span><span class=\"s1\">&#39;var&#39;</span><span class=\"p\">:</span> <span class=\"n\">obj</span><span class=\"p\">},</span> <span class=\"n\">autoescape</span><span class=\"o\">=</span><span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">autoescape</span><span class=\"p\">)</span>\n    <span class=\"c1\"># ... Do something with new_context ...</span>\n</code></pre></div>\n<p>Ce n’est pas une situation très courante, mais c’est utile si vous faites vous-même le rendu d’un gabarit. Par exemple :</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=\"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=\"p\">):</span>\n    <span class=\"n\">t</span> <span class=\"o\">=</span> <span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">template</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=\"s1\">&#39;small_fragment.html&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">t</span><span class=\"o\">.</span><span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">Context</span><span class=\"p\">({</span><span class=\"s1\">&#39;var&#39;</span><span class=\"p\">:</span> <span class=\"n\">obj</span><span class=\"p\">},</span> <span class=\"n\">autoescape</span><span class=\"o\">=</span><span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">autoescape</span><span class=\"p\">))</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"1.8\">\n<p class=\"version-note-title\">Changed in Django 1.8</p><p>L’attribut <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> des objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Context</span></code> a été ajouté dans Django 1.8. <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/api/#django.template.Engine.get_template\" title=\"django.template.Engine.get_template\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">context.template.engine.get_template</span></code></a> doit être utilisé à la place de <a class=\"reference internal\" href=\"/fr/1.9/topics/templates/#django.template.loader.get_template\" title=\"django.template.loader.get_template\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">django.template.loader.get_template()</span></code></a> parce que ce dernier renvoie désormais un adaptateur dont la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render</span></code> n’accepte pas d’objet <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/api/#django.template.Context\" title=\"django.template.Context\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Context</span></code></a>.</p>\n</aside>\n<p>Si nous avions négligé de passer la valeur actuelle de <code class=\"docutils literal notranslate\"><span class=\"pre\">context.autoescape</span></code> au nouveau <code class=\"docutils literal notranslate\"><span class=\"pre\">Context</span></code> de cet exemple, les résultats auraient <em>toujours</em> subi un échappement automatique, ce qui pourrait ne pas correspondre au comportement attendu si la balise de gabarit est utilisée à l’intérieur d’un bloc  <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-autoescape\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">autoescape</span> <span class=\"pre\">off</span> <span class=\"pre\">%}</span></code></a>.</p>\n</section>\n<section id=\"thread-safety-considerations\">\n<span id=\"template-tag-thread-safety\"></span><h3>Considérations sur la concurrence entre « threads »<a class=\"heading-anchor\" href=\"#thread-safety-considerations\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Dès qu’un nœud est analysé, sa méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render</span></code> peut être appelée indéfiniment. Comme Django est parfois lancé dans un environnement avec plusieurs fils d’exécution parallèles (multi-thread), un même nœud peut être rendu plusieurs fois simultanément avec différents contextes en réponse à des requêtes séparées. Il est donc important de s’assurer que vos balises de gabarit sont robustes à la concurrence.</p>\n<p>Pour que vos balises de gabarit sachent gérer la concurrence, il ne faut jamais stocker des informations d’état dans le nœud lui-même. Par exemple, Django contient une balise de gabarit <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-cycle\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">cycle</span></code></a> qui parcourt une liste de chaînes données à chaque rendu :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">o</span> <span class=\"k\">in</span> <span class=\"nv\">some_list</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">tr</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">cycle</span> <span class=\"s1\">&#39;row1&#39;</span> <span class=\"s1\">&#39;row2&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n        ...\n    <span class=\"p\">&lt;/</span><span class=\"nt\">tr</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Une implémentation naïve de <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode</span></code> pourrait ressembler à 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=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">itertools</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CycleNode</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">cyclevars</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cycle_iter</span> <span class=\"o\">=</span> <span class=\"n\">itertools</span><span class=\"o\">.</span><span class=\"n\">cycle</span><span class=\"p\">(</span><span class=\"n\">cyclevars</span><span class=\"p\">)</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=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"nb\">next</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cycle_iter</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Mais supposons que deux gabarits soient rendus en parallèle et qu’ils contiennent l’extrait de gabarit ci-dessus :</p>\n<ol class=\"arabic simple\">\n<li><p>Le fil d’exécution 1 effectue sa première itération de boucle, <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode.render()</span></code> renvoie « row1 »</p></li>\n<li><p>Le fil d’exécution 2 effectue sa première itération de boucle, <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode.render()</span></code> renvoie « row2 »</p></li>\n<li><p>Le fil d’exécution 1 effectue sa seconde itération de boucle, <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode.render()</span></code> renvoie « row1 »</p></li>\n<li><p>Le fil d’exécution 2 effectue sa seconde itération de boucle, <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode.render()</span></code> renvoie « row2 »</p></li>\n</ol>\n<p>Le nœud CycleNode effectue son itération, mais globalement. En ce qui concerne les fils d’exécution 1 et 2, ils renvoient toujours la même valeur. Ce n’est évidemment pas ce que nous voulons !</p>\n<p>Pour résoudre ce problème, Django met à disposition un <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</span></code> qui est associé au <code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code> du gabarit qui est en cours de rendu. <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</span></code> se comporte comme un dictionnaire Python et doit être utilisé pour stocker l’état de <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> entre les invocations de la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render</span></code>.</p>\n<p>Révisons notre implémentation de <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode</span></code> en utilisant <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CycleNode</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">cyclevars</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cyclevars</span> <span class=\"o\">=</span> <span class=\"n\">cyclevars</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=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span> <span class=\"ow\">not</span> <span class=\"ow\">in</span> <span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">render_context</span><span class=\"p\">:</span>\n            <span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">render_context</span><span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">itertools</span><span class=\"o\">.</span><span class=\"n\">cycle</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cyclevars</span><span class=\"p\">)</span>\n        <span class=\"n\">cycle_iter</span> <span class=\"o\">=</span> <span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">render_context</span><span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"p\">]</span>\n        <span class=\"k\">return</span> <span class=\"nb\">next</span><span class=\"p\">(</span><span class=\"n\">cycle_iter</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Notez qu’il est totalement correct de stocker sous forme d’attribut de l’information globale qui ne changera pas durant le cycle de vie de <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code>. Dans le cas de <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode</span></code>, le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">cyclevars</span></code> ne change plus après que <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> a été instancié, nous n’avons donc pas besoin de le placer dans <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</span></code>.  Mais l’information d’état qui est spécifique au gabarit en cours de rendu, comme l’état d’itération de <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode</span></code>, doit être stockée dans <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</span></code>.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Remarquez la manière dont nous avons utilisé <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code> pour délimiter l’information spécifique de <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNode</span></code> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</span></code>. Il peut y avoir plusieurs <code class=\"docutils literal notranslate\"><span class=\"pre\">CycleNodes</span></code> dans un gabarit donné, il faut donc être prudent de ne pas empiéter sur l’information d’état d’un autre nœud. La façon la plus simple de faire cela est de toujours utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code> comme clé dans <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context</span></code>. Si vous conservez la trace de plusieurs variables d’état, faites de <code class=\"docutils literal notranslate\"><span class=\"pre\">render_context[self]</span></code> un dictionnaire.</p>\n</aside>\n</section>\n<section id=\"registering-the-tag\">\n<h3>Inscription de la balise<a class=\"heading-anchor\" href=\"#registering-the-tag\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour terminer, inscrivez la balise dans l’instance <code class=\"docutils literal notranslate\"><span class=\"pre\">Library</span></code> de votre module, comme expliqué dans la section sur l”<a class=\"reference internal\" href=\"#howto-writing-custom-template-tags\"><span class=\"std std-ref\">écriture des filtres de gabarit personnalisés</span></a> ci-dessus. Exemple :</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=\"n\">register</span><span class=\"o\">.</span><span class=\"n\">tag</span><span class=\"p\">(</span><span class=\"s1\">&#39;current_time&#39;</span><span class=\"p\">,</span> <span class=\"n\">do_current_time</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">tag()</span></code> accepte deux paramètres :</p>\n<ol class=\"arabic simple\">\n<li><p>Le nom de la balise de gabarit (une chaîne). En cas d’omission, c’est le nom de la fonction de compilation qui sera utilisé.</p></li>\n<li><p>La fonction de compilation, une fonction Python (et non pas le nom de la fonction sous forme de chaîne).</p></li>\n</ol>\n<p>Comme pour l’inscription de filtre, il est aussi possible d’utiliser une syntaxe de décorateur :</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=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">tag</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;current_time&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_current_time</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span><span class=\"n\">tag</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">shout</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Si vous omettez le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> comme dans le second exemple ci-dessus, Django utilise le nom de la fonction comme nom de balise.</p>\n</section>\n<section id=\"passing-template-variables-to-the-tag\">\n<h3>Transmission de variables de gabarit à la balise<a class=\"heading-anchor\" href=\"#passing-template-variables-to-the-tag\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Même si vous pouvez transmettre autant de paramètres que souhaité à la balise de gabarit en utilisant <code class=\"docutils literal notranslate\"><span class=\"pre\">token.split_contents()</span></code>, les paramètres sont alors tous identifiés comme chaînes de caractères. Pour pouvoir passer du contenu dynamique (une variable de gabarit) comme paramètre d’une balise de gabarit, cela demande un petit peu plus d’effort.</p>\n<p>Dans les exemples précédents, l’heure actuelle a été formatée en chaîne et celle-ci a été renvoyée en tant que chaîne. Supposons que nous souhaitions passer un <a class=\"reference internal\" href=\"/fr/1.9/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a> d’un objet pour que la balise de gabarit mette en forme cette date :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>This post was last updated at <span class=\"cp\">{%</span> <span class=\"k\">format_time</span> <span class=\"nv\">blog_entry.date_updated</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"cp\">%}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Initialement, <code class=\"docutils literal notranslate\"><span class=\"pre\">token.split_contents()</span></code> renverra trois valeurs :</p>\n<ol class=\"arabic simple\">\n<li><p>Le nom de la balise</p></li>\n<li><p>La chaîne <code class=\"docutils literal notranslate\"><span class=\"pre\">'blog_entry.date_updated'</span></code> (sans les guillemets).</p></li>\n<li><p>La chaîne de formatage <code class=\"docutils literal notranslate\"><span class=\"pre\">'&quot;%Y-%m-%d</span> <span class=\"pre\">%I:%M</span> <span class=\"pre\">%p&quot;'</span></code>. La valeur de retour de <code class=\"docutils literal notranslate\"><span class=\"pre\">split_contents()</span></code> contiendra les guillemets ouvrant et fermant pour de telles chaînes constantes.</p></li>\n</ol>\n<p>Votre balise devrait maintenant commencer à ressembler à 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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_format_time</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># split_contents() knows not to split quoted strings.</span>\n        <span class=\"n\">tag_name</span><span class=\"p\">,</span> <span class=\"n\">date_to_be_formatted</span><span class=\"p\">,</span> <span class=\"n\">format_string</span> <span class=\"o\">=</span> <span class=\"n\">token</span><span class=\"o\">.</span><span class=\"n\">split_contents</span><span class=\"p\">()</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag requires exactly two arguments&quot;</span> <span class=\"o\">%</span> <span class=\"n\">token</span><span class=\"o\">.</span><span class=\"n\">contents</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"ow\">and</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"s1\">&#39;&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&#39;&quot;</span><span class=\"p\">)):</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag&#39;s argument should be in quotes&quot;</span> <span class=\"o\">%</span> <span class=\"n\">tag_name</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">FormatTimeNode</span><span class=\"p\">(</span><span class=\"n\">date_to_be_formatted</span><span class=\"p\">,</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Vous devez aussi modifier la fonction de rendu pour récupérer le contenu réel de la propriété <code class=\"docutils literal notranslate\"><span class=\"pre\">date_updated</span></code> de l’objet <code class=\"docutils literal notranslate\"><span class=\"pre\">blog_entry</span></code>. Cela peut se faire en utilisant la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Variable()</span></code> de <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template</span></code>.</p>\n<p>Pour utiliser la clase <code class=\"docutils literal notranslate\"><span class=\"pre\">Variable</span></code>, il suffit de l’instancier avec le nom de la variable à résoudre puis d’appeler <code class=\"docutils literal notranslate\"><span class=\"pre\">variable.resolve(context)</span></code>. Ainsi, par exemple :</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">FormatTimeNode</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">date_to_be_formatted</span><span class=\"p\">,</span> <span class=\"n\">format_string</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">date_to_be_formatted</span> <span class=\"o\">=</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Variable</span><span class=\"p\">(</span><span class=\"n\">date_to_be_formatted</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span> <span class=\"o\">=</span> <span class=\"n\">format_string</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=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"n\">actual_date</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">date_to_be_formatted</span><span class=\"o\">.</span><span class=\"n\">resolve</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n            <span class=\"k\">return</span> <span class=\"n\">actual_date</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span><span class=\"p\">)</span>\n        <span class=\"k\">except</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">VariableDoesNotExist</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<p>La résolution de variable lèvera une exception <code class=\"docutils literal notranslate\"><span class=\"pre\">VariableDoesNotExist</span></code> si elle ne peut pas résoudre la chaîne qui lui a été passée dans le contexte actuel de la page.</p>\n</section>\n<section id=\"setting-a-variable-in-the-context\">\n<h3>Définition d’une variable dans le contexte<a class=\"heading-anchor\" href=\"#setting-a-variable-in-the-context\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les exemples ci-dessus ne font qu’afficher une valeur. Il est généralement plus souple de définir des variables de gabarit dans les balises de gabarit que d’afficher des valeurs. De cette façon, les auteurs de gabarits peuvent réutiliser les valeurs créées par vos balises de gabarit.</p>\n<p>Pour définir une variable dans le contexte, il suffit d’attribuer des valeurs à l’objet dictionnaire du contexte dans la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code>. Voici une version mise à jour de <code class=\"docutils literal notranslate\"><span class=\"pre\">CurrentTimeNode</span></code> qui définit une variable de gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">current_time</span></code> au lieu de l’afficher :</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\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">template</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CurrentTimeNode2</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">format_string</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span> <span class=\"o\">=</span> <span class=\"n\">format_string</span>\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=\"p\">):</span>\n        <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;current_time&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<p>Notez que <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> renvoie la chaîne vide. <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> doit toujours renvoyer une chaîne. Si la balise de gabarit ne fait que définir une variable, <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> doit renvoyer la chaîne vide.</p>\n<p>Voici comment on pourrait utiliser cette nouvelle version de la balise :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%M-%d %I:%M %p&quot;</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{{</span> <span class=\"nv\">current_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<aside class=\"admonition-variable-scope-in-context admonition\">\n<p class=\"admonition-title\">Portées des variables dans le contexte</p>\n<p>Toute variable définie dans le contexte ne sera disponible que dans le même « bloc » de gabarit dans lequel elle a été définie. Ce comportement est voulu ; il définit la portée des variables afin qu’elles n’entrent pas en conflit avec le contexte d’autres blocs.</p>\n</aside>\n<p>Mais il reste un problème avec <code class=\"docutils literal notranslate\"><span class=\"pre\">CurrentTimeNode2</span></code>: le nom de variable <code class=\"docutils literal notranslate\"><span class=\"pre\">current_time</span></code> est codé en dur. Cela veut dire que vous devrez vous assurer que votre gabarit n’utilise pas <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">current_time</span> <span class=\"pre\">}}</span></code> ailleurs, parce que <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">current_time</span> <span class=\"pre\">%}</span></code> va écraser de manière aveugle la valeur de cette éventuelle variable. Une solution plus propre est de permettre à la balise de gabarit de définir le nom de la variable produite, comme ceci :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%M-%d %I:%M %p&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">my_current_time</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The current time is <span class=\"cp\">{{</span> <span class=\"nv\">my_current_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Pour faire cela, il faudra modifier à la fois la fonction de compilation et la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code>, comme 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=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">re</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CurrentTimeNode3</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">format_string</span><span class=\"p\">,</span> <span class=\"n\">var_name</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span> <span class=\"o\">=</span> <span class=\"n\">format_string</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">var_name</span> <span class=\"o\">=</span> <span class=\"n\">var_name</span>\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=\"p\">):</span>\n        <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">var_name</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">format_string</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_current_time</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"c1\"># This version uses a regular expression to parse tag contents.</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># Splitting by None == splitting by spaces.</span>\n        <span class=\"n\">tag_name</span><span class=\"p\">,</span> <span class=\"n\">arg</span> <span class=\"o\">=</span> <span class=\"n\">token</span><span class=\"o\">.</span><span class=\"n\">contents</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag requires arguments&quot;</span> <span class=\"o\">%</span> <span class=\"n\">token</span><span class=\"o\">.</span><span class=\"n\">contents</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n        <span class=\"p\">)</span>\n    <span class=\"n\">m</span> <span class=\"o\">=</span> <span class=\"n\">re</span><span class=\"o\">.</span><span class=\"n\">search</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;(.*?) as (\\w+)&#39;</span><span class=\"p\">,</span> <span class=\"n\">arg</span><span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">m</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span><span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag had invalid arguments&quot;</span> <span class=\"o\">%</span> <span class=\"n\">tag_name</span><span class=\"p\">)</span>\n    <span class=\"n\">format_string</span><span class=\"p\">,</span> <span class=\"n\">var_name</span> <span class=\"o\">=</span> <span class=\"n\">m</span><span class=\"o\">.</span><span class=\"n\">groups</span><span class=\"p\">()</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"ow\">and</span> <span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"s1\">&#39;&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&#39;&quot;</span><span class=\"p\">)):</span>\n        <span class=\"k\">raise</span> <span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">TemplateSyntaxError</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag&#39;s argument should be in quotes&quot;</span> <span class=\"o\">%</span> <span class=\"n\">tag_name</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">CurrentTimeNode3</span><span class=\"p\">(</span><span class=\"n\">format_string</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">],</span> <span class=\"n\">var_name</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>La différence ici est que <code class=\"docutils literal notranslate\"><span class=\"pre\">do_current_time()</span></code> capture la chaîne de format et le nom de la variable, les transmettant les deux à <code class=\"docutils literal notranslate\"><span class=\"pre\">CurrentTimeNode3</span></code>.</p>\n<p>Finalement, si vous n’avez besoin que d’une syntaxe simple pour votre balise de gabarit de mise à jour du contexte, envisagez l’utilisation du raccourci <a class=\"reference internal\" href=\"#django.template.Library.simple_tag\" title=\"django.template.Library.simple_tag\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">simple_tag()</span></code></a> qui permet d’attribuer le résultat de la balise à une variable de gabarit.</p>\n</section>\n<section id=\"parsing-until-another-block-tag\">\n<h3>Analyse jusqu’à la prochaine balise de bloc<a class=\"heading-anchor\" href=\"#parsing-until-another-block-tag\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les balises de gabarit peuvent travailler en tandem. Par exemple, la balise <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-comment\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code></a> standard masque tout jusqu’à la prochaine occurrence de <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code>. Pour créer une balise de gabarit semblable, utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.parse()</span></code> dans votre fonction de compilation.</p>\n<p>Voici comment une balise <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code> simplifiée pourrait être écrite :</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_comment</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"n\">nodelist</span> <span class=\"o\">=</span> <span class=\"n\">parser</span><span class=\"o\">.</span><span class=\"n\">parse</span><span class=\"p\">((</span><span class=\"s1\">&#39;endcomment&#39;</span><span class=\"p\">,))</span>\n    <span class=\"n\">parser</span><span class=\"o\">.</span><span class=\"n\">delete_first_token</span><span class=\"p\">()</span>\n    <span class=\"k\">return</span> <span class=\"n\">CommentNode</span><span class=\"p\">()</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CommentNode</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>L’implémentation effective de <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-comment\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code></a> est légèrement différente dans la mesure où elle autorise des balises incorrectes à apparaître entre <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code>. Elle fait cela en appelant <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.skip_past('endcomment')</span></code> au lieu de <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.parse(('endcomment',))</span></code>, suivi par <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.delete_first_token()</span></code>, ce qui évite de générer une liste de nœuds.</p>\n</aside>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">parser.parse()</span></code> accepte un tuple de noms de balises bloc définissant les limites d’analyse. Elle renvoie une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">django.template.NodeList</span></code> contenant une liste de tous les objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</span></code> que l’analyseur a rencontré avant que n’apparaisse  l’une des balises indiquées dans le tuple.</p>\n<p>Dans <code class=\"docutils literal notranslate\"><span class=\"pre\">nodelist</span> <span class=\"pre\">=</span> <span class=\"pre\">parser.parse(('endcomment',))</span></code> de l’exemple ci-dessus, <code class=\"docutils literal notranslate\"><span class=\"pre\">nodelist</span></code> est une liste de tous les nœuds entre <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code>, à l’exclusion de <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code>.</p>\n<p>Après l’appel à <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.parse()</span></code>, l’analyseur n’a pas encore « consommé » la balise <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code>, c’est pourquoi le code doit explicitement appeler <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.delete_first_token()</span></code>.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">CommentNode.render()</span></code> renvoie simplement une chaîne vide. Tout ce qui se trouve entre <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code> est ignoré.</p>\n</section>\n<section id=\"parsing-until-another-block-tag-and-saving-contents\">\n<h3>Analyse jusqu’à la prochaine balise de bloc et enregistrement du contenu<a class=\"heading-anchor\" href=\"#parsing-until-another-block-tag-and-saving-contents\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Dans l’exemple prédédent, <code class=\"docutils literal notranslate\"><span class=\"pre\">do_comment()</span></code> a ignoré tout ce qui apparaissait entre <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">comment</span> <span class=\"pre\">%}</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endcomment</span> <span class=\"pre\">%}</span></code>. Au lieu de faire cela, il est possible de faire quelque chose avec le code situé entre les balises de bloc.</p>\n<p>Par exemple, voici une balise de gabarit personnalisée, <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">upper</span> <span class=\"pre\">%}</span></code>, qui met en majuscules tout ce qui se trouve entre elle et <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">endupper</span> <span class=\"pre\">%}</span></code>.</p>\n<p>Utilisation :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">upper</span> <span class=\"cp\">%}</span>This will appear in uppercase, <span class=\"cp\">{{</span> <span class=\"nv\">your_name</span> <span class=\"cp\">}}</span>.<span class=\"cp\">{%</span> <span class=\"k\">endupper</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Comme dans l’exemple précédent, nous utilisons <code class=\"docutils literal notranslate\"><span class=\"pre\">parser.parse()</span></code>. Mais cette fois-ci, nous passons le contenu de <code class=\"docutils literal notranslate\"><span class=\"pre\">nodelist</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">Node</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_upper</span><span class=\"p\">(</span><span class=\"n\">parser</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"p\">):</span>\n    <span class=\"n\">nodelist</span> <span class=\"o\">=</span> <span class=\"n\">parser</span><span class=\"o\">.</span><span class=\"n\">parse</span><span class=\"p\">((</span><span class=\"s1\">&#39;endupper&#39;</span><span class=\"p\">,))</span>\n    <span class=\"n\">parser</span><span class=\"o\">.</span><span class=\"n\">delete_first_token</span><span class=\"p\">()</span>\n    <span class=\"k\">return</span> <span class=\"n\">UpperNode</span><span class=\"p\">(</span><span class=\"n\">nodelist</span><span class=\"p\">)</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UpperNode</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">Node</span><span class=\"p\">):</span>\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\">nodelist</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nodelist</span> <span class=\"o\">=</span> <span class=\"n\">nodelist</span>\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=\"p\">):</span>\n        <span class=\"n\">output</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nodelist</span><span class=\"o\">.</span><span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">output</span><span class=\"o\">.</span><span class=\"n\">upper</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Le seul nouveau concept ici est l’appel à <code class=\"docutils literal notranslate\"><span class=\"pre\">self.nodelist.render(context)</span></code> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">UpperNode.render()</span></code>.</p>\n<p>Pour plus d’exemples de rendus complexes, consultez le code source des balises <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">for</span> <span class=\"pre\">%}</span></code></a> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">django/template/defaulttags.py</span></code> et <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-if\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">if</span> <span class=\"pre\">%}</span></code></a> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">django/template/smartif.py</span></code>.</p>\n</section>\n</section>","rootId":"custom-template-tags-and-filters","toc":[{"title":"Disposition du code","anchor":"code-layout","children":[]},{"title":"Écriture de filtres de gabarits personnalisés","anchor":"writing-custom-template-filters","children":[{"title":"Inscription de filtres personnalisés","anchor":"registering-custom-filters","children":[]},{"title":"Filtres de gabarits agissant sur des chaînes","anchor":"template-filters-that-expect-strings","children":[]},{"title":"Les filtres et l’échappement automatique","anchor":"filters-and-auto-escaping","children":[]},{"title":"Filtres et fuseaux horaires","anchor":"filters-and-time-zones","children":[]}]},{"title":"Écriture de balises de gabarits personnalisées","anchor":"writing-custom-template-tags","children":[{"title":"Balises simples","anchor":"simple-tags","children":[]},{"title":"Balises d’inclusion","anchor":"inclusion-tags","children":[]},{"title":"Balises d’attribution","anchor":"assignment-tags","children":[]},{"title":"Balises de gabarits personnalisées (niveau avancé)","anchor":"advanced-custom-template-tags","children":[]},{"title":"Aperçu rapide","anchor":"a-quick-overview","children":[]},{"title":"Écriture de la fonction de compilation","anchor":"writing-the-compilation-function","children":[]},{"title":"Écriture de la fonction de rendu","anchor":"writing-the-renderer","children":[]},{"title":"Considérations sur l’échappement automatique","anchor":"auto-escaping-considerations","children":[]},{"title":"Considérations sur la concurrence entre « threads »","anchor":"thread-safety-considerations","children":[]},{"title":"Inscription de la balise","anchor":"registering-the-tag","children":[]},{"title":"Transmission de variables de gabarit à la balise","anchor":"passing-template-variables-to-the-tag","children":[]},{"title":"Définition d’une variable dans le contexte","anchor":"setting-a-variable-in-the-context","children":[]},{"title":"Analyse jusqu’à la prochaine balise de bloc","anchor":"parsing-until-another-block-tag","children":[]},{"title":"Analyse jusqu’à la prochaine balise de bloc et enregistrement du contenu","anchor":"parsing-until-another-block-tag-and-saving-contents","children":[]}]}],"breadcrumbs":[{"docname":"howto/index","title":"Guides pratiques","url":"/fr/1.9/howto/"}],"prev":{"docname":"howto/custom-lookups","title":"Expressions de recherche personnalisées","url":"/fr/1.9/howto/custom-lookups/"},"next":{"docname":"howto/custom-file-storage","title":"Écriture d’un système de stockage personnalisé","url":"/fr/1.9/howto/custom-file-storage/"},"formats":{"html":"/fr/1.9/howto/custom-template-tags/","markdown":"/fr/1.9/howto/custom-template-tags.md","json":"/fr/1.9/howto/custom-template-tags.json"},"source":"https://github.com/django/django/blob/stable/1.9.x/docs/howto/custom-template-tags.txt","official":"https://docs.djangoproject.com/fr/1.9/howto/custom-template-tags/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","fr","ja","id","pt-br","es"]}