2017-10-28 5 views
1

Ich habe ein Django-Modell mit vielen Feldern. Sagen wir, das Modell ist wie folgt:Wie erhalte ich mithilfe von Django-Abfragen die Anzahl der einzelnen Werte aus verschiedenen Feldern?

class Foo(models.Model): 
    name = models.CharField(max_length=50) 
    type = models.CharField(max_length=100, blank=True) 
    foo_value = models.CharField(max_length=14, blank=True) 
    # ... and many many other fields 

Jetzt muss ich eine Abfrage ausführen, mir alle Daten aus allen Bereichen zu erhalten. Das wäre Foo.objects.all(), oder?

Jetzt brauche ich für jeden Namen (was bedeutet, dass ich nach Namen gruppieren werde), um einige Dinge zu tun. Erstens, das Problem ist, wenn ich nach Namen gruppieren möchte, würde ich dies tun: Foo.objects.values('name'), richtig? Aber das bringt mir die 'Name' Feldwert nur für alle Datensätze. Ich brauche alle anderen Felder aber gruppiert von Name.

Die zweite wichtige Sache ist, ich brauche die Zählung eines jeden eindeutigen Wert in der ‚Typ‘ Feld sowie die Summe der ‚foo_value‘ Feld mit jedem verbunden bekommen ' Typ '. Ich brauche all dies zu einem Datensatz pro 'Name' in das zurückgegebene Ergebnis. Das Problem ist, wenn ich dies versucht: Foo.objects.values('name').annotate(c=Count('type'), s=Sum('foo_value')), es mir einen Datensatz für jeden bekommen (‚Namen‘, ‚Typen‘) Paar.
Was ich brauche, ist, dass, wenn ich Daten wie folgt aus:

Name         Typ         foo_value
x                 t1                 5,5
x                 t1                 10,0
x                 t2                 20.0
y                 t2                 15.23
y                 t1                 17,0

Ich brauche das Ergebnis zu sein:

Name         type_t1_count         type_t1_sum         type_t2_count         type_t2_sum
x                                                             15,5                                                                                             20,0
y                                                             17.0                                                                                             15,23

Wie so etwas wie dies zu erreichen?

+0

_I brauchen alle anderen Felder, aber gruppiert nach Name._ - Sie können andere Felder nicht erhalten, weil .. zum Beispiel haben Sie mehrere Modelle mit dem gleichen Namen, aber andere Felder sind unterschiedlich. Welches Modell von mehreren willst du bekommen? Scheint so, dass du 'order_by' brauchst, nicht gruppieren! – zvadym

Antwort

2

Seit django 1.8 hat conditional-expressions und Sie können versuchen, und Sie shoul order_by verwenden Standardgruppe auszuschließen, indem docs lesen:

from django.db.models import Count, Case, When, IntegerField, FloatField 

qs = Foo.objects.values('name' 
        ).annotate(type_t1_count=Count(
         Case(
          When(type='t1', then=1), 
          output_field=IntegerField() 
         ) 
         ) 
        ).annotate(type_t1_sum=Sum(
         Case(
          When(type='t1', then='foo_value'), 
          default=0.0, 
          output_field=FloatField() 
         ) 
         ) 
        ).annotate(type_t2_count=Count(
         Case(
          When(type='t2', then=1), 
          output_field=IntegerField() 
         ) 
         ) 
        ).annotate(type_t2_sum=Sum(
         Case(
          When(type='t2', then='foo_value'), 
          default=0.0, 
          output_field=FloatField() 
         ) 
         ) 
        ).order_by('name') 

das Ergebnis:

[ 
    {'type_t1_sum': 15.5, 'type_t1_count': 2, 
    'type_t2_count': 1, 'type_t2_sum': 20.0, 
    'name': 'x'}, 
    {'type_t1_sum': 17.0, 'type_t1_count': 1, 
    'type_t2_count': 1, 'type_t2_sum': 15.23, 
    'name': 'y'} 
] 
+0

vielen Dank. Das hat total funktioniert. Ich habe noch eine Sache, wenn du mir helfen kannst. Für eines der Felder in meinem Modell muss ich den Moduswert berechnen (den gebräuchlichsten Wert). Aber es funktioniert so: – Ahmedn1

+0

Es ist ein 'DateTimeField' im Modell. Also habe ich die Abfrage erhalten und dann den Tag-Wert mit 'q ['event_time']. Day 'ermittelt und dann das Viertel des Monats mit dem' bisect'-Paket berechnet. Ich füge dann alle Quartiere für alle Datensätze desselben Benutzers zu einer Liste hinzu und erhalte dann den Modus dieser Liste mit dem 'numpy' Statistikpaket. So, hier ist der Code: 'Quart = range (1, 31, 7);' ' Quartal = bisect (Quart, q [ 'event_time'] Tag.);' ' month_quarts.append (Quartal, wenn Quartal <= 4 else 4); ' und später bekomme ich den Modus mit' qm = mode (month_quarts); ' – Ahmedn1

+0

Gibt es eine Möglichkeit, dies mit dem' When .. then' Ausdruck zu tun? – Ahmedn1

Verwandte Themen