2010-03-23 10 views
14

en mi aplicación Django 1.1.1 Tengo una función en la vista que devuelve a su plantilla un rango de números y una lista de listas de elementos, por ejemplo :Utilizando forloop.counter value como índice de lista en una plantilla de 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]) 

Dentro de la plantilla tengo una externa para el bucle, que contiene también otro para el ciclo que se mostrará en la salida contiene una de las listas internas de datos de esta manera

... 
{% 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 %} 
... 

Pero Django el motor de plantilla no funciona con el valor forloop.counter0 como índice para t lista (en cambio sí lo hace si coloco manualmente un valor numérico como índice). ¿Hay alguna manera de dejar que el bucle de lista funcione con el valor externo forloop.counter0? Gracias de antemano por la ayuda :)

Respuesta

12

No puede usar variables para los nombres de atributos, las teclas del diccionario o los índices de la lista.

También range(0,len(data)-1] no es válido python. Debe ser range(len(data)).

Probablemente no necesite cycle. Tal vez lo que quiere es esto:

{% 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

Gracias Stefanw, es exactamente lo que estaba tratando de hacer, no pensé en iterar sobre la lista porque en el caso de 'len (data) == 1' (sí, el uno que escribí antes no era una buena declaración de Python) Tuve que mostrar la salida de la lista de una manera diferente. De todos modos ahora parece que todo está funcionando, ¡gracias de nuevo por tu ayuda! – Alex

+0

Esta es definitivamente la forma correcta de hacerlo, pero [aquí] (http://stackoverflow.com/a/11784863/456848) es cómo trabajo alrededor de "sin variables como nombres de atributos, claves de diccionario o índices de listas" problema. No es elegante estar seguro, pero lo hace al usar etiquetas y filtros integrados. –

17

Resolví esto de una manera bastante ineficiente. Por favor no vomites en tu computadora cuando leas este código. Dadas dos listas de longitud idéntica, recorrerá la primera e imprimirá el elemento correspondiente de la segunda.

Si debe usar esto, solo utilícelo para plantillas a las que rara vez se accede, donde la longitud de ambas listas será pequeña. Idealmente, refactorice los datos de su plantilla para evitar este problema por completo.

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

Realmente no puedo imaginar una situación en la que esta sea la mejor solución posible. – acjay

3

quería tener alternando los colores en mi mesa con una hoja de estilo, haciendo pasar una lista de alternar los valores verdadero/falso. Encontré esto realmente frustrante. Al final, creé una lista de elementos de diccionario con las mismas teclas que los campos en la tabla, más uno más con el valor de alternar verdadero/falso.

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 

y mi plantilla

{% 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 %} 
Cuestiones relacionadas