Templates Django : tags et filtres personnalisés
Rappels sur les tags et filtres de templates
Dans nos vues (templates) Django, nous utilisons généralement des variables positionnées dans le contexte via les contrôleurs (views) ou des context processors. Pour manipuler ces variables et les présenter au mieux, nous disposons de deux types d'outils :
- Les filtres, qui permettent de modifier le rendu des variables. Exemple :
{{ une_chaine|lower }}
permet de convertir la chaîneune_chaine
en minuscules pour affichage. - Les tags, qui permettent des manipulations plus complexes des variables, par exemple des itérations (boucles), l'extension de templates, etc. Exemple d'utilisation d'un tag :
{% for objet in liste_objets %} {{ objet.name }} {% endfor %}
Création de filtres et tags perso
Dans certaines situations, il est commode de pouvoir définir ses propres filtres et tags. Ceci est rendu possible très simplement par Django. Les filtres et tags custom sont définis au niveau de chaque application. Nous allons pour cela :
- Créer un répertoire
templatetags
dans le répertoire de l'application. - Créer dans ce répertoire un fichier Python destiné à contenir nos tags.
- Implémenter dans ce fichier autant de fonctions que nécessaire, une fonction correspondant à un tag.
Les fonctions définissant des tags peuvent disposer du contexte du template depuis lequel ils sont appelés, ainsi que de paramètres éventuellement passés via l'appel du tag ou filtre dans le template.
Pas clair ? Imaginons que vous souhaitiez insérer sur vos pages des offres de produits issues du site Amazon (comme vous pouvez en voir sur certaines pages de ce site de formation à Django). Pour faire ceci, Amazon met à votre disposition des portions de code à insérer directement sur votre site, et qui ressemblent à ceci :
<a href="http://www.amazon.fr/gp/product/2212134150/ref=as_li_ss_il?ie=UTF8&camp=1642&creative=19458&creativeASIN=2212134150&linkCode=as2&tag=imaensom-21"><img border="0" src="http://ws-eu.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=2212134150&Format=_SL160_&ID=AsinImage&MarketPlace=FR&ServiceVersion=20070822&WS=1&tag=imaensom-21" ></a><img src="http://ir-fr.amazon-adsystem.com/e/ir?t=imaensom-21&l=as2&o=8&a=2212134150" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
Pas très folichon, n'est-ce pas ? Plutôt que d'insérer manuellement à chaque fois, et étant donné que les produits Amazon sont repérés par leur référence ASIN, ne serait-il pas plus pratique de disposer d'un tag de template qui ferait la même chose et que l'on pourrait utiliser de la sorte :
{% amazon_snippet "reference_asin" %}
Voilà qui est plus élégant. Voyons maintenant comment implémenter ce tag amazon_snippet
.
Un tag Django personnalisé amazon_snippet pour les produits Amazon
Avant d'écrire le code, comprenons bien les choses. Notre tag aura besoin, pour fonctionner :
- d'un paramètre
asin
, via lequel l'utilisateur du tag pourra spécifier la référence du produit qu'il souhaite afficher ; - éventuellement de la référence affilié de l'utilisateur du tag (et oui, il faut bien faire un peu de business comme on peut).
Voici le code de notre tag perso Amazon.
context_processor.pyfrom django.conf import settings
def amazon_snippet(context, asin):
"""
Tag permettant d'afficher l'image Amazon d'un produit en fonction de son
ASIN, avec lien vers la fiche article + tag affilié.
"""
amazon_affiliate_id = settings.AMAZON_ID
offer_url = 'http://www.amazon.fr/gp/product/{asin}/ref=as_li_ss_il?ie=UTF8&camp=1642&creative=19458&creativeASIN={asin}&linkCode=as2&tag={amazon_affiliate_id}'.format(asin=asin, amazon_affiliate_id=amazon_affiliate_id)
image_url = 'http://ws-eu.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN={asin}&Format=_SL160_&ID=AsinImage&MarketPlace=FR&ServiceVersion=20070822&WS=1&tag={amazon_affiliate_id}'.format(asin=asin, amazon_affiliate_id=amazon_affiliate_id)
snippet = '<a href="{offer_url}"><img src="{image_url}" alt="Produit Amazon" /></a>'.format(offer_url=offer_url, image_url=image_url)
return snippet
Quelques remarques concernant ce tag perso Amazon :
- Pour trouver l'ID affilié de l'utilisateur, notre fonction fait appel à la configuration du projet via
settings
: il faut obligatoirement ajouter, dans le fichier settings.py, une constante nomméeAMAZON_ID
, qui doit contenir l'ID affilié. Laissé en exercice : il est bien sûr possible de modifier le code ci-dessus pour tester si la constanteAMAZON_ID
est définie ou non danssettings.py
, et gérer le cas où elle ne l'est pas (par exemple, en créant une URL sans le paramètretag
…). - Nous construisons l'URL de la fiche article (
offer_url
) ainsi que l'URL de l'image du produit à afficher (image_url
) en utilisant la fonction format expliquée dans l'introduction à Python, formattage de chaînes de caractères. - Notre fonction tag perso retourne une chaîne de caractère : l'appel du tag sera remplacé, à l'exécution, dans la vue (template), par le contenu de cette chaîne, tout simplement.
Est-ce qu'il marche, ce tag personnalisé Amazon Django ?
Le site de cette formation Django utilise une version analogue du tag défini ci-dessus. Voici le résultat :
Et voici le code de l'appel, dans la vue (template) :
page.html{% amazon_snippet "2212134150" %}