2010-03-23 6 views
14

dans mon application Django 1.1.1 J'ai une fonction dans la vue qui renvoie à son template une plage de nombres et une liste de listes d'items, par exemple :Utilisation de la valeur forloop.counter comme index de liste dans un template Django

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

A l'intérieur du modèle que j'ai un externe pour la boucle, qui contient aussi une autre pour le cycle à afficher dans la sortie contient des listes internes de données 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 Django Le moteur de gabarit ne fonctionne pas avec la valeur forloop.counter0 comme index pour t Il liste (à la place, si je mets manuellement une valeur numérique comme index). Est-il un moyen de laisser la boucle de liste fonctionne avec la valeur forloop.counter0 externe? Merci d'avance pour l'aide :)

Répondre

12

Vous ne pouvez pas utiliser de variables pour les noms d'attribut, les clés de dictionnaire ou les listes indicielles.

Aussi range(0,len(data)-1] n'est pas valide python. Il devrait être range(len(data)).

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

{% 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 %} 
+0

Merci Stefanw, c'est exactement ce que j'essayais de faire, je ne pensais pas itérer sur la liste parce que dans le cas de 'len (data) == 1' (oui, le celui que j'ai écrit auparavant n'était pas une bonne déclaration en python) J'ai dû montrer la sortie de la liste d'une manière différente. Quoi qu'il en soit, tout semble fonctionner, merci encore pour votre aide! – Alex

+0

C'est certainement la bonne façon de le faire, mais [ici] (http://stackoverflow.com/a/11784863/456848) est comment je contourne le "pas de variables comme noms d'attributs, clés de dictionnaire, ou index de liste" problème. Il est inélégant pour être sûr, mais il le fait en utilisant uniquement des balises et des filtres intégrés. –

17

J'ai résolu cela d'une manière plutôt inefficace. S'il vous plaît ne pas vomir sur votre ordinateur lorsque vous lisez ce code. Étant donné deux listes de longueur identique, il parcourra la première et imprimera l'élément correspondant de la seconde.

Si vous devez l'utiliser, utilisez-le uniquement pour les modèles rarement consultés pour lesquels la longueur des deux listes sera réduite. Idéalement, refactorisez les données de votre modèle pour éviter complètement ce problème.

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

Je ne peux vraiment pas imaginer une situation où ce serait la meilleure solution possible. – acjay

3

Je voulais avoir des couleurs en alternance dans ma table en utilisant une feuille de style, en passant une liste de valeurs Vrai/basculement Faux. J'ai trouvé cela vraiment frustrant. À la fin, 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 true/false de bascule.

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 %} 
Questions connexes