== Templates === Structure et configuration ==== Répertoires de découverte des templates [source,bash] ---- $ tree templates/ templates/ └── wish └── list.html ---- Par défaut, Django cherchera les templates dans les répertoirer d'installation. Vous devrez vous éditer le fichier `gwift/settings.py` et ajouter, dans la variable `TEMPLATES`, la clé `DIRS` de la manière suivante: [source,python] ---- TEMPLATES = [ { ... 'DIRS': [ 'templates' ], ... }, ] ---- ==== Fichiers statiques (à compléter) === Builtins Django vient avec un ensemble de *tags* ou *template tags*. On a vu la boucle `for` ci-dessus, mais il existe https://docs.djangoproject.com/fr/1.9/ref/templates/builtins/[beaucoup d'autres tags nativement présents]. Les principaux sont par exemple: * `{% if ... %} ... {% elif ... %} ... {% else %} ... {% endif %}`: permet de vérifier une condition et de n'afficher le contenu du bloc que si la condition est vérifiée. * Opérateurs de comparaisons: `<`, `>`, `==`, `in`, `not in`. * Regroupements avec le tag `{% regroup ... by ... as ... %}`. * `{% url %}` pour construire facilement une URL à partir de son nom * `urlize` qui permet de remplacer des URLs trouvées dans un champ de type CharField ou TextField par un lien cliquable. * ... Chacune de ces fonctions peut être utilisée autant au niveau des templates qu'au niveau du code. Il suffit d'aller les chercher dans le package `django.template.defaultfilters`. Par exemple: [source,python] ---- from django.db import models from django.template.defaultfilters import urlize class Suggestion(models.Model): """Représentation des suggestions. """ subject = models.TextField(verbose_name="Sujet") def urlized_subject(self): """ Voir https://docs.djangoproject.com/fr/3.0/howto/custom-template-tags/ """ return urlize(self.subject, autoescape=True) ---- ==== Regroup By (le truc super facile qui sert à mort dans plein de cas sans qu'on n'ait à se casser la tête). === Non-builtins En plus des quelques tags survolés ci-dessus, il est également possible de construire ses propres tags. La structure est un peu bizarre, car elle consiste à ajouter un paquet dans une de vos applications, à y définir un nouveau module et à y définir un ensemble de fonctions. Chacune de ces fonctions correspondra à un tag appelable depuis vos templates. Il existe trois types de tags *non-builtins*: 1. *Les filtres* - on peut les appeler grâce au *pipe* `|` directement après une valeur dans le template. 2. *Les tags simples* - ils peuvent prendre une valeur ou plusieurs en paramètre et retourne une nouvelle valeur. Pour les appeler, c'est *via* les tags `{% nom_de_la_fonction param1 param2 ... %}`. 3. *Les tags d'inclusion*: ils retournent un contexte (ie. un dictionnaire), qui est ensuite passé à un nouveau template. Type `{% include '...' ... %}`. Pour l'implémentation: 1. On prend l'application `wish` et on y ajoute un répertoire `templatetags`, ainsi qu'un fichier `__init__.py`. 2. Dans ce nouveau paquet, on ajoute un nouveau module que l'on va appeler `tools.py` 3. Dans ce module, pour avoir un aperçu des possibilités, on va définir trois fonctions (une pour chaque type de tags possible). [source,bash] ---- [Inclure un tree du dossier template tags] ---- Pour plus d'informations, la https://docs.djangoproject.com/en/stable/howto/custom-template-tags/#writing-custom-template-tags[documentation officielle est un bon début]. ==== Filtres [source,python] ---- # wish/tools.py from django import template from wish.models import Wishlist register = template.Library() @register.filter(is_safe=True) def add_xx(value): return '%sxx' % value ---- ==== Tags simples [source,python] ---- # wish/tools.py from django import template from wish.models import Wishlist register = template.Library() @register.simple_tag def current_time(format_string): return datetime.datetime.now().strftime(format_string) ---- ==== Tags d'inclusion [source,python] ---- # wish/tools.py from django import template from wish.models import Wishlist register = template.Library() @register.inclusion_tag('wish/templatetags/wishlists_list.html') def wishlists_list(): return { 'list': Wishlist.objects.all() } ---- === Contexts Processors Un `context processor` permet d'ajouter des informations par défaut à un contexte (le dictionnaire qu'on passe de la vue au template). L'idée est d'ajouter une fonction à un module Python à notre projet, puis de le référencer parmi les CONTEXT_PROCESSORS de nos paramètres généraux. Cette fonction doit peupler un dictionnaire, et les clés de ce dictionnaire seront directement ajoutées à tout autre dictionnaire/contexte passé à une vue. Par exemple: (cf. https://stackoverflow.com/questions/60515797/default-context-for-all-pages-django[StackOverflow] - à retravailler) [source,python] ---- from product.models import SubCategory, Category def add_variable_to_context(request): return { 'subCategories': SubCategory.objects.order_by('id').all(), 'categories': Category.objects.order_by("id").all(), } ---- [source,python] ---- 'OPTIONS': { 'context_processors': [ .... 'core.context_processors.add_variable_to_context', .... ], }, ----