Des blocks dans des blocks dans des blocks , dans des …

Tout ceux qui font du django, ont, un jour, utilisés des blocks pour écrire un template. Pour rappel, un block c’est un moyen de délimiter un ’bout’ de template.

A quoi ca sert un block ? Très rapide rappel

Imaginons que vous faites un blog. Votre blog peut afficher soit un post, soit une liste de post, soit une catégorie, soit une liste de catégorie. Dans tout les cas, vous aurez des menus à droites et à gauches et même au dessus.
Vous allez peut-être décider de faire un template ‘base’ où vous allez définir les choses qui ne changeront jamais, ici les menus.
Ensuite il faut trouver une façon simple de pouvoir soit afficher un post, soit une catégorie, etc etc ..

Rien de plus simple. Dans la base vous définissez un block content par exemple :

{% block content %}
{% endblock %}

Maintenant dans votre template qui s’occupe d’afficher les posts, il suffira de dire que vous étendez base puis de redéfinir le block content et op, vous aurez à la fois tout vos menus définis dans base mais aussi votre nouveau content.

{% extends "base.html" %}

{% block content %}
     {{post}}
{% endblock %}

Bien entendu, on est pas obligé de redéfinir tout les blocks de template qu’on étends. Si on ne redéfinit pas un block , le contenu du block parent sera utilisé. (Par exemple, si on reprend l’idée du blog, ce n’est pas seulement un block content qu’il faut définir, mais aussi un block pour chacun de nos menus. Ces block ne seront pas redéfinis dans le template post, c’est donc ceux de base qui seront utilisés)

des blocks dans des blocks.

Jusqu’à présent, je n’ai fait que faire un très rapide rappel de ce que c’était qu’un block en django. (Pour ceux qui veulent en savoir plus, la doc de django est là pour ça).

La petite astuce que je voulais mettre en lumière dans ce billet arrive maintenant. En fait c’est tout simple, c’est qu’on peut parfaitement imbriquer des blocks dans d’autre.

Ceci :

{% block content %}

    {% block content_intra_content %}

    {% endblock %}

{% endblock %}

Fonctionne parfaitement. A quoi cela pourrait servir ? Pourquoi ne pas faire deux blocks l’un en dessous de l’autre ?

Pour la première question, je me suis creusé la tête pour trouver un exemple. Je crois en avoir trouvé un. Imaginons qu’on doit afficher différentes données, toute de la même manière. Mais que par contre , en fonction des données en question , on a un menu ‘Actions possibles’ différents.

Pour reprendre mon exemple de blog, cela serait afficher la liste des catégories ou la listes des posts.

On pourrait donc décider de faire les choses ainsi  dans le template liste :

{% extends "base.html" %}

    {% block content %}

    {% block actions  %}

{% endblock %}

    {% block content_intra_content %}
         Ici on affiche des trucs ...
    {% endblock %}
{% endblock %}

puis dans le template liste_categorie :

{% extends "liste.html" %}

    {% block actions  %}
         {{categorie_actions}}
    {% endblock %}

Je ne suis pas sur que ce soit le meilleur exemple, ni même qu’au final, l’imbrication des blocks aient une quelconque utilité, mais comme en testant, je me suis rendu compte que c’était possible, je me suis dit que j’allais en parler (Et comme ça si des gens ont un avis sur l’utilité de cette pratique, je les aurais en commentaire)

Deux derniers petits trucs

Le tags {{ block.super }} qui permet dans un block fils de récupérer le contenu d’un block père pour l’afficher. A utiliser quand on ne veut pas redéfinir un block mais simplement l’enrichir.
Il est possible de remettre le nom du block dans le tags de fin de block comme ceci :

{% extends "base.html" %}

{% block content %}

{% endblock content  %}

Ca ne sert à rien, à part à rendre plus clair les choses.

L’algèbre du Q (et du queryset)

Oui, je sais, mon titre de billet n’est pas des plus fin.. Tans pis, c’est la faute au surmenage.

J’avais déjà parlé des objets Q dans un précédent billet. Pour mémoire les objets Q sont des objets django qui permettent de faire de filtrer des requêtes BD d’une façon plus poussée qu’en simplement chainant des appels à filter.

L’algèbre des Q

Les opérateurs ET (&) et OU ( | ) fonctionne sur les objects Q. On peut les chainer, en faire des expressions complexes en parenthésant sans aucun problème.

L’algèbre des queryset

Les queryset sont des objets itérable qui sont renvoyés, par, entre autre, la fonction filter et qui stockent le résultat d’une requête BD. On s’en sert aussi pour remplir les différents composants ‘à choix’ d’un formulaire (selectlist,etc… ).

On ne peut pas concaténer deux queryset comme on pourrait le faire avec deux listes avec par exemple L1 + L2. Mais les queryset supporte les opérations logique. On peut donc là aussi faire des OU (ce qui revient à les concaténer) et des ET pour trouver l’intersection entre deux queryset.

Et c’est, plus que bien utile.