2016-05-21 5 views
6

ich von dem Charakter name Feld jedes Datensatzes und begrenzen Sie die Elemente in jeder Gruppe zu Gruppe Aufzeichnungen versuchen, hier ist, was ich kam haben sich mit:Django Gruppenobjekt durch das erste Zeichen einer Spalte

desired_letters = ['a','b','c',..,'z'] 
some_variable = {} 
for desired_letter in desired_letters: 
    some_variable += User.objects.all().order_by("name").filter(name__startswith=desired_letter)[:10] 

Und ich führe diese Abfrage in einer for-Schleife und ändern desired_letter zu meinem gewünschten Brief, gibt es eine andere Möglichkeit, diese Lösung zu optimieren und es zu einer einzigen Abfrage anstelle einer for-Schleife machen?

+0

Ok, so wie können wir helfen? –

+0

@MosesKoledoye Ich muss dies optimieren und machen Sie es vielleicht eine einzige Abfrage mit 'values ​​()' Funktion – samix73

+0

Diese Gruppe von macht keinen Sinn macht es? Wenn Sie nach dem ersten Buchstaben des Benutzernamens gruppieren, erhalten Sie nur 26 Datensätze. Ist das wonach Sie suchen? – e4c5

Antwort

8

Von dem Kommentar in der anderen Antwort:

ich nach einem Weg suchte eigentlich Group By First Character zu implementieren in django

orm ich es in der folgenden drei Schritte tun würde:

  1. Beschriften Sie jeden Datensatz mit dem ersten Buchstaben des Felds name. Dafür könnten Sie Substr Funktion zusammen mit Lower

    from django.db.models.functions import Substr, Lower 
    qs = User.objects.annotate(fl_name=Lower(Substr('name', 1, 1))) 
    
  2. Als nächstes Gruppe alle Datensätze mit diesem Anfangsbuchstaben verwenden und die Anzahl der IDs erhalten. Dies kann durch Verwendung annotate with values erfolgen:

    # since, we annotated each record we can use the first letter for grouping, and 
    # then get the count of ids for each group 
    from django.db.models import Count 
    qs = qs.values('fl_name').annotate(cnt_users=Count('id')) 
    
  3. Als nächstes Sie diese queryset mit dem ersten Buchstaben bestellen:

    qs = qs.order_by('fl_name') 
    

Die Kombination all diese in einer Aussage:

from django.db.models.functions import Substr, Lower 
from django.db.models import Count 

qs = User.objects \ 
     .annotate(fl_name=Lower(Substr('name', 1, 1))) \ 
     .values('fl_name') \ 
     .annotate(cnt_users=Count('id')) \ 
     .order_by('fl_name') 

An der e nd, Ihr Anfrage-Set würde ungefähr so ​​aussehen. Beachten Sie, dass ich das erste Zeichen beim Annotieren in Kleinbuchstaben umgewandelt habe. Wenn Sie nicht, dass benötigen, können Sie die Lower Funktion entfernen:

[{'fl_name': 'a', 'cnt_users': 12}, 
{'fl_name': 'b', 'cnt_users': 4}, 
... 
... 
{'fl_name': 'z', 'cnt_users': 3},] 

Wenn Sie ein Wörterbuch von Buchstaben benötigen und zählen:

fl_count = dict(qs.values('fl_name', 'cnt_users')) 
# {'a': 12, 'b': 4, ........., 'z': 3} 
2

erste Bestellung und dann Filterung ist übertrieben und umsonst. Sie sollten nur die Daten bestellen, die Sie benötigen. Ansonsten bestellen Sie alle Zeilen nach Namen und dann filtern und schneiden, was Sie brauchen.

ich tun würde:

User.objects.filter(name__startswith=desired_letter).order_by("name")[:10] 

und .all() überflüssig war.

+0

danke für die Antwort, wie wäre es mit der Gruppierung, gibt es einen anderen Weg als die Verwendung von for-Schleife? – samix73

+0

@ samix73 können Sie Ihre for-Schleife zeigen? – doniyor

+0

Ich habe die Frage bearbeitet, ich war tatsächlich auf der Suche nach einer Möglichkeit, [this] (http://stackoverflow.com/questions/666525/group-by-first-character) in Django Orm zu implementieren – samix73

Verwandte Themen