web-dev-qa-db-fra.com

Coloration alternée des lignes dans Django modèle avec plusieurs ensembles de lignes

Les modèles Django offrent la balise intégrée cycle pour alterner entre plusieurs valeurs à différents points dans un modèle (ou pour une boucle dans un modèle) mais cette balise ne se réinitialise pas lorsqu'elle est accessible dans une portée en dehors de cycles définition. Autrement dit, si vous avez deux ou plusieurs listes dans votre modèle, les lignes de toutes celles que vous souhaitez utiliser certaines définitions CSS odd et even, la première ligne d'une liste choisira là où le dernier s'est arrêté, pas avec une nouvelle itération des choix (odd et even)

Par exemple, dans le code suivant, si le premier blog a un nombre impair d'entrées, alors la première entrée dans un deuxième blog commencera comme even, quand je veux qu'il commence à odd.

{% for blog in blogs %}
  {% for entry in blog.entries %}
    <div class="{% cycle 'odd' 'even' %}" id="{{entry.id}}">
      {{entry.text}}
    </div>
  {% endfor %}
{% endfor %}

J'ai essayé d'éviter cela en corrigeant avec la balise resetcycle offerte ici:

ticket Django: la balise Cycle doit se réinitialiser après avoir quitté la portée

en vain. (Le code n'a pas fonctionné pour moi.)

J'ai également essayé de déplacer ma boucle interne dans une balise personnalisée, mais cela n'a pas fonctionné non plus, peut-être parce que le cycle de compilation/rendu ramène la boucle dans la boucle externe? (Peu importe pourquoi, cela n'a pas fonctionné pour moi.)

Comment puis-je accomplir cette tâche simple!? Je préférerais ne pas créer une structure de données à mon avis avec ces informations précompilées; cela semble inutile. Merci d'avance.

58
Carl G

La solution de contournement la plus simple (jusqu'à ce que le correctif resetcycle soit corrigé et appliqué) consiste à utiliser le filtre "divisibleby" intégré avec forloop.counter:

{% for entry in blog.entries %}
  <div class="{% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}" id="{{ entry.id }}">
    {{ entry.text }}
  </div>
{% endfor %}

Un peu plus verbeux, mais pas difficile à comprendre et ça marche très bien.

111
Carl Meyer

https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#cycle

{% for o in some_list %}
    <tr class="{% cycle 'row1' 'row2' %}">
        ...
    </tr>
{% endfor %}
14
Matt

Vous pouvez utiliser les appels balisés cycle et resetcycle (nouveau dans Django 1.11) (depuis https://docs.djangoproject.com/en /1.11/ref/templates/builtins/#std:templatetag-resetcycle ):

{% for blog in blogs %}
  {% cycle 'odd' 'even' as rowcolors silent %}
  {% resetcycle rowcolors %}
  {% for entry in blog.entries %}
    {% cycle rowcolors %}
    <div class="{{ rowcolors }}" id="{{entry.id}}">
      {{ entry.text }}
    </div>
  {% endfor %}
{% endfor %}
3
emi

Je finis par le faire, avec le forloop.counter0 - Cela fonctionne très bien!

{% for product in products %}

    {% if forloop.counter0|divisibleby:4 %}<div class="clear"></div>{% endif %}

    <div class="product {% if forloop.counter0|divisibleby:4 %}col{% else %}col20{% endif    %}">
        Lorem Ipsum is simply dummy text
    </div>

{% endfor %}
2
pkdkk

La réponse la plus simple pourrait être: "abandonner et utiliser jQuery". Si c'est acceptable, c'est probablement plus facile que de se battre avec les modèles de Django pour quelque chose de si simple.

1
Steve Losh

Abandonnez et utilisez Jinja2 Template System

J'ai abandonné le langage de modèle Django, il est très limité dans ce que vous pouvez en faire. Jinja2 utilise la même syntaxe que le modèle Django utilise, mais ajoute de nombreuses améliorations par-dessus.

EDIT/NOTE (Je sais que cela ressemble à un gros interrupteur pour un problème mineur, mais en réalité, je parie que vous vous retrouvez toujours à combattre le système de modèles par défaut à Django, donc cela en vaut vraiment la peine et je pense que cela vous rendra plus productif à long terme.)

Vous pouvez lire cet article écrit par son auteur , bien que ce soit technique, il mentionne le problème de la balise {% cycle%} dans Django.

Jinja n'a pas d'étiquette de cycle, il a une méthode de cycle sur la boucle:

{% for user in users %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
{% endfor %}

Un avantage majeur de Jinja2 est qu'il vous permet d'utiliser la logique pour la présentation, donc si vous avez une liste d'images, vous pouvez les mettre dans un tableau, car vous pouvez commencer une nouvelle ligne dans un tableau tous les N éléments, voir, vous pouvez faire par exemple:

{% if loop.index is divisibleby(5) %}   
     </tr>
     {% if not loop.last %}
     <tr>
     {% endif %}
{% endif %}

vous pouvez également utiliser des expressions mathématiques:

{% if x > 10 %}

et vous pouvez accéder à vos fonctions python directement (mais une configuration est requise pour spécifier les fonctions à exposer pour le modèle)

{% for item in normal_python_function_that_returns_a_query_or_a_list() %}

même définir des variables ..

{% set variable_name = function_that_returns_an_object_or_something() %} 
1
hasen