web-dev-qa-db-fra.com

Utilisation de la valeur forloop.counter comme index de liste dans un modèle Django

dans mon application Django 1.1.1, la fonction affiche une fonction qui renvoie à son modèle une plage de nombres et une liste de listes d'éléments, par exemple:

...  
data=[[item1 , item2, item3], [item4, item5, item6], [item7, item8, item9]]  
return render_to_response('page.html', {'data':data, 'cycle':range(0,len(data)-1])

À l'intérieur du modèle, j'ai une boucle for externe, qui contient également une autre boucle à afficher en sortie le contenu des listes de données internes de cette manière.

...  
{% for page in cycle %}   
...   
< table >   
{% for item in data.forloop.counter0 %}  
< tr >< td >{{item.a}} < /td > < td > {{item.b}} ... < /td > < /tr >  
...  
< /table >  
{% endfor %}  
{% if not forloop.last %}  
< div class="page_break_div" >  
{% endif %}  
{% endfor %}  
... 

Mais le moteur de template Django ne fonctionne pas avec la valeur forloop.counter0 en tant qu'index pour la liste (c'est le cas si je mets manuellement une valeur numérique en tant qu'index). Est-il possible de laisser la boucle de liste fonctionner avec la valeur forloop.counter0 externe? Merci d'avance pour l'aide :)

15
Alex

Vous ne pouvez pas utiliser de variables pour les noms d'attributs, les clés de dictionnaire ou les index de liste.

De plus, range(0,len(data)-1] n'est pas valide en python. Ce devrait être range(len(data)).

Vous n'avez probablement pas besoin de cycle. Peut-être que ce que vous voulez, c'est ceci:

{% for itemlist in data %}
    ...
    <table>
        {% for item in itemlist %}
        <tr>
          <td>{{ item.a }}</td>
          <td>{{ item.b }} ... </td>
        </tr>
        ...
        {% endfor %}
    </table>
    {% if not forloop.last %}
        <div class="page_break_div">
    {% endif %}
{% endfor %}
12
stefanw

J'ai résolu ce problème de manière plutôt inefficace. S'il vous plaît, ne jetez pas sur votre ordinateur lorsque vous lisez ce code. Avec deux listes de longueur identique, il parcourra la première et imprimera l'élément correspondant à partir de la seconde.

Si vous devez utiliser ceci, utilisez-le uniquement pour les modèles rarement consultés où la longueur des deux listes sera réduite. Idéalement, reformulez les données de votre modèle pour éviter ce problème.

{% for list1item in list1 %}
   {% for list2item in list2 %}
      {% if forloop.counter == forloop.parentloop.counter %}
          {{ list1item }} {{ list2item }}
      {% endif %}
   {% endfor %}
{% endfor %}
17
Mark

Je souhaitais alterner les couleurs dans mon tableau à l'aide d'une feuille de style, en passant une liste de valeurs True/False. J'ai trouvé cela vraiment frustrant. Finalement, j'ai créé une liste d'éléments de dictionnaire avec les mêmes clés que les champs de la table, plus un autre avec la valeur de basculement vraie/fausse.

def jobListView(request):
    # Django does not allow you to append stuff to the job identity, neither
    # will it allow forloop.counter to index another list. The only solution
    # is to have the toggle embedded in a dictionary along with
    # every field from the job
    j                   = job.objects.order_by('-priority')
    # have a toggling true/false list for alternating colours in the table
    theTog              = True
    jobList             = [] 
    for i in j:
        myJob           = {}
        myJob['id']     = i.id
        myJob['duty']   = i.duty
        myJob['updated'] = i.updated
        myJob['priority'] = i.priority
        myJob['description'] = i.description
        myJob['toggle'] = theTog
        jobList.append(myJob)
        theTog          = not(theTog)
    # next i

    return render_to_response('index.html', locals())
# end jobDetaiView

et mon modèle

{% if jobList %}
    <table border="1"><tr>
    <th>Job ID</th><th>Duty</th><th>Updated</th><th>Priority</th><th>Description</th>
    </tr>

    {% for myJob in jobList %}

        <!-- only show jobs that are not closed and have a positive priority. -->
        {% if myJob.priority and not myJob.closeDate %}
            <!-- alternate colours with the classes defined in the style sheet -->
            {% if myJob.toggle %}
                <tr class=d1> 
            {% else %}
                <tr class=d0>
            {% endif %}

            <td><a href="/jobs/{{ myJob.id }}/">{{ myJob.id }}</td><td>{{ myJob.duty }}</td> 
            <td>{{ myJob.updated }}</td><td>{{ myJob.priority }}</td>
            <td class=middle>{{ myJob.description }}</td>
            </tr>
        {% endif %}
    {% endfor %}
    </ul>
{% else %}
    <p>No jobs are in the system.</p>
{% endif %}
3
Jason

Utilisez forloop.last - True s'il s'agit du dernier passage dans la boucle:

{% if forloop.last %}
{% endif %}

From Balises et filtres de modèles intégrés

0
Cubiczx