Intro
Voici un problème qui mérite un petit article. Le système de grille (bootstrap grid) de bootstrap est formidable seulement il n'est pas très dynamique quant au nombre d'éléments à y inclure. Voici donc comment établir une grille dans un template Django avec un nombre inconnu d'élément.
Solution
Imaginons que nous souhaitons établir une grille à 3 colonnes, voici la version statique (6 éléments, 2 lignes, 3 colonnes) :
<div class="container">
<div class="row">
<div class="col-md-4">
élément 1
</div>
<div class="col-md-4">
élément 2
</div>
<div class="col-md-4">
élément 3
</div>
</div>
<div class="row">
<div class="col-md-4">
élément 4
</div>
<div class="col-md-4">
élément 5
</div>
<div class="col-md-4">
élément 6
</div>
</div>
</div>
Jusqu'à la, tout va bien, sauf que c'est pas dynamique.
Prenons par exemple des postes de blog Wagtail, la boucle initiale est la suivante:
{% for post in self.get_children.specific %}
{% endfor %}
Ici, nous ne connaissons pas le nombre de poste. Le premier élément à déployer est le compteur de boucle:
{{ forloop.counter }}
Inséré dans une boucle for, il compte tout simplement les tours.
A noter que celui ci-dessus démarre à 1, pour les puristes qui souhaiteraient commencer à 0, il est possible d'utiliser {{ forloop.counter0 }}
Jusqu'ici tout va bien, maintenant il s'agit de tester le modulo du compteur de boucle, s'il est égal à 0 il faut créer une nouvelle ligne dans la grille. En d'autres termes, si je veux une grille à 3 colonnes, je vais tester si le compteur de boucle est divisible par 3.
<div class="container">
<div class="row">
{% for post in self.get_children.specific %}
{% if forloop.counter|divisibleby:3 %}
<div class="col-md-4">
{{ post.title }}
</div>
</div>
{% if not forloop.last %}
<div class="row">
{% endif %}
{% else %}
<div class="col-md-4">
{{ post.title }}
</div>
{% endif %}
{% endfor %}
</div>
</div>