2010-11-11 18 views
12

Ho un QuerySet come:Django raggruppa il queryset con la prima lettera?

items = Item.objects.all() 

Item ha un campo 'nome'. Nel modello voglio mostrare:

  • Un
  • Assi
  • alcool
  • B
  • Bazookas
  • C
  • Monete
  • cartucce
  • S
  • Swords
  • Passeri

Così le voci sono ordinate e di gruppo per la prima lettera. Le lettere mancanti sono omesse. Qualcuno ha qualche idea?

risposta

19

C'è un tag modello per questo, se tutto quello che ti interessa è la sua presentazione sulla pagina. Innanzitutto, definisci un principio organizzativo nella classe. Nel tuo caso, è la prima lettera:

class Item(models.Model): 
    ... 

    def first_letter(self): 
     return self.name and self.name[0] or '' 

e quindi definire un Raggruppamento nel modello, utilizzando la chiamata first_letter:

{% regroup items by first_letter as letter_list %} 
<ul> 
{% for letter in letter_list %} 
    <li>{{ letter.grouper }} 
    <ul> 
     {% for item in letter.list %} 
     <li>{{ item.name }}</li> 
     {% endfor %} 
    </ul> 
    </li> 
{% endfor %} 
</ul> 
+0

Grazie, gentile signore! :) Quel metodo all'interno del modello era il mio pezzo mancante. – Tudorizer

+0

ottimo modo per risolvere il problema. stava cercando di mixare http://stackoverflow.com/questions/4151631/django-grouping-queryset-by-first-letter/4151742#4151742 e questo insieme https://djangosnippets.org/snippets/889/ –

+4

Tu don ' Ho bisogno del metodo sulla classe, dato che puoi usare i filtri nel tag di registro. Puoi semplicemente '{% raggruppare gli elementi per nome | first | upper come letter_list%}' –

6

Volevo solo aggiungere che se si utilizza questo e il vostro articolo ha un primo carattere minuscolo sarà un gruppo separato. Ho aggiunto quello superiore.

return self.name and self.name.upper()[0] or '' 
4

In alternativa è possibile utilizzare slice linea nel modello, senza la necessità di un metodo first_letter del modello.

{% regroup items by name|slice:":1" as letter_list %} 
<ul> 
{% for letter in letter_list %} 
    <li>{{ letter.grouper }} 
    <ul> 
     {% for item in letter.list %} 
     <li>{{ item.name }}</li> 
     {% endfor %} 
    </ul> 
    </li> 
{% endfor %} 
</ul> 
+0

Questa soluzione è meglio IMHO –

0

Ancora più semplice. È possibile raggruppare in primo luogo leter solo in 'riorganizzarsi':

{% regroup items|dictsort:"name" by name.0 as item_letter %} 
<ul> 
{% for letter in item_letter %} 
    <h4>{{ letter.grouper|title }}</h4> 
    {% for i in letter.list|dictsort:"name" %} 
     <li>{{ i.name }}</li> 
    {% endfor %} 
{% empty %} 
    <span>There is no items yet...</span> 
{% endfor %} 
</ul> 

name.0 in questo caso lo stesso di item.name[0] in Python.

Testato in Django 1.10

Problemi correlati