2016-05-23 7 views
2

Wie summiere Preisgruppe nach Monat?Django Annotate-Gruppe nach Monat

Ich versuche es.

import itertools 
qs = Contract.objects.values('created', 'proposal__price') 
grouped = itertools.groupby(qs, lambda d: d.get('created').strftime('%Y-%m')) 
data = [{'month': month, 'quant': sum(list(this_day))} for month, this_day in grouped] 
print(data) 

Aber das Ergebnis ist nicht zu erwarten.

Ich brauche dieses ähnliches Ergebnis

[{'month': '2016-04', 'quant': 8650}, {'month': '2016-05', 'quant': 9050}] 
+0

Mögliches Duplikat von [So gruppieren Sie nach UND-Aggregat mit Django] (http://stackoverflow.com/questions/13403609/how-to-group-by-and-aggregate-with-django) –

+0

Mögliches Duplikat von [ Django: Gruppieren nach Datum (Tag, Monat, Jahr)] (http://stackoverflow.com/questions/8746014/django-group-by-date-day-month-year) – tback

Antwort

1

Ihre this_day innerhalb sum(list(this_day)) ist ein dict, so dass Sie eine Liste mit einer Liste Verständnis aufbauen müssen. Beispiel

>>> import itertools 
>>> from django.contrib.auth.models import User 
>>> li = User.objects.all().values('date_joined', 'username') 
>>> gr = itertools.groupby(li, lambda d: d.get('date_joined').strftime('%Y-%m')) 
>>> dt = [{'m': m, 'q': sum([len(x['username']) for x in q])} for m, q in gr] 
>>> dt 
[{'m': '2005-06', 'q': 11}, {'m': '2006-10', 'q': 22}, 
{'m': '2005-06', 'q': 179}, {'m': '2006-08', 'q': 10}, 
{'m': '2006-09', 'q': 30}, {'m': '2005-06', 'q': 74}, ... ] 

Oder für Ihren Code, wahrscheinlich so etwas wie dieses

data = [{'month': month, 'quant': sum([x['proposal__price'] for x in this_day])} 
     for month, this_day in grouped] 
0

starten durch den Monat zu extrahieren und alle Werte

from django.db import connection 
select = {'month': connection.ops.date_trunc_sql('month', 'created')} 
qs = Contract.objects.extra(select=select).values('month').annotate(my_total=Sum('proposal__price')) 

Jetzt haben wir eine Funktion Gruppe verwenden können dict Schlüssel wie folgt:

from itertools import groupby 
from operator import attrgetter 
get_y = attrgetter('month') 
from collections import defaultdict, Counter 
def solve(dataset, group_by_key, sum_value_keys): 
    dic = defaultdict(Counter) 
    for item in dataset: 
     key = item[group_by_key] 
     vals = {k:item[k] for k in sum_value_keys} 
     dic[key].update(vals) 
    return dic 

es zu Ihrem queryset des Nehmen neu my_total kommentierten, gruppiert nach month:

solved = solve(qs, 'month', ['my_total']) 

Und Sie Summen werden nach Monat gruppiert (Monat ein Datetime-Objekt sein kann, Ihre Bedürfnisse ändern manipulieren):

for i in solved: print(i, ":", solved[i]['my_total']) 
>>> datetime.datetime(2015, 9, 1, 0, 0, tzinfo=<UTC>) : 67614.23 
>>> datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<UTC>) : 54792.39 

Jetzt können Sie diese Werte extrahieren :)

+0

Ihr Code Ergebnis dieser Fehler: 'return Database .Cursor.execute (self, query, params) django.db.utils.OperationalError: mehrdeutiger Spaltenname: erstellt ' –

+0

Ich benutze Sqlite3. –

0

Mein Code angepasst von @ C14L.

import itertools 
# from .models import Contract 
c = Contract.objects.all().values('created', 'proposal__price') 
gr = itertools.groupby(c, lambda d: d.get('created').strftime('%Y-%m')) 
dt = [{'month': month, 'quant': sum([x['proposal__price'] for x in quant])} for month, quant in gr] 
dt 

Danke.