2010-12-31 10 views
2

Ich möchte die Anzahl der Elemente für jede Liste auflisten. Wie kann ich diese Nummer in einer einzelnen Abfrage statt in einer Abfrage für jede Liste finden? HierDjango: Abfragen optimieren

ist eine vereinfachte Version meiner aktuellen Template-Code:

{% for list in lists %} 
<li> 
{{ listname }}: 
{% with list.num_items as item_count %} 
{{ item_count }} item{{ item_count|pluralize }} 
{% endwith %} 
</li> 
{% endfor %} 

Listen geführt wird, wie: List.objects.filter (user = user)

und NUM_ITEMS ist eine Eigenschaft des List-Modell :

def _get_num_items(self): 
    return self.item_set.filter(archived=False).count() 
num_items = property(_get_num_items) 

Dieser fragt SELECT COUNT(*) FROM "my_app_item" WHERE... n-mal, wobei n die Anzahl der Listen ist. Ist es möglich, hier eine einzige Abfrage zu machen?

+0

http://docs.djangoproject.com/en/dev/topics/db/aggregation/ –

+0

Ignacio, Er fragt, wie man die "gruppierten Aggregate in einer einzigen Abfrage" erhält, auf die die Dokumentation, auf die Sie verweisen, nicht verweist. Ich rede nicht darüber. –

+0

@Lakshman: Nur wenn Sie es nicht lesen. –

Antwort

1

Sie sollten dies in Ihrer Sicht tun und stattdessen das Wörterbuch senden.

Model.objects.values_list('item').annotate(Count('num_items')) 

Dies wird die gleiche SQL produzieren wie (oder gleichwertig) die, die Sie gebucht haben.

1

Im Folgenden habe ich versucht, alle Ihre Einschränkungen zu berücksichtigen: Filtern auf Felder der Liste, auf Felder von Item, zählen Elemente und Gruppierung nach Liste.

Die Lösung, die ich sehe, ist, dass Sie Werte verwenden könnten() (hier ist die django doc dazu: http://docs.djangoproject.com/en/dev/topics/db/aggregation/#values)

from django.db.models import Count 
lists = list(List.objects.filter(user=user)) 
items=Item.objects.values(list).filter(archived=False,list__in=lists).annotate(count=Count("id")) 
#you will get a list of dicts of the form [{'count':2,'list':5},...] where 5 is the id of the list 
#now, you can match you list with you item counts in python 
list_items_count_dict={} 
for item in items: 
    list_items_count_dict[item['list']]=item['count'] 
for list in lists : 
    list.item_count = list_items_count_dict.get(list.id) 

, dass nur 2 Abfragen machen, eine für die Listen bekommen, die andere für Berechnen der Artikelanzahl. Danach haben Sie zwei Schleifen (das wahrscheinlich durch Liste Verständnis Einzeiler ersetzt werden könnte), sondern nur für die Listen sind Sie interessiert.

danach, in der Vorlage, können Sie

verwenden
{{list.item_count}} 

Es könnte eine elegantere Option geben, aber das habe ich gerade gefunden. Ich bin auch sicher, dass Sie die Anzahl der Abfrage auf einen reduzieren konnten, indem Sie benutzerdefinierte SQL verwenden.

Haftungsausschluss: Ich habe diesen Code nicht getestet, aber ich habe ähnlichen Code auf ähnlichen Modellen getestet. Sie könnten Probleme haben, weil list eines der Schlüsselwörter der Python-Sprache ist.