Innanzitutto, devi creare una funzione che possa estrarre il mese per te:
from django.db import models
from django.db.models import Func
class Month(Func):
function = 'EXTRACT'
template = '%(function)s(MONTH from %(expressions)s)'
output_field = models.IntegerField()
Dopodiché tutto ciò che devi fare è
- annota ogni riga con il mese
- raggruppa i risultati per mese annotato utilizzando
values()
- annota ogni risultato con la somma aggregata dei totali usando
Sum()
Importante :se la tua classe modello ha un ordinamento predefinito specificato nelle meta opzioni, dovrai aggiungere un order_by()
vuoto clausola. Ciò è dovuto a https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by
Campi citati in order_by()
parte di un set di query (o che vengono utilizzati nell'ordinamento predefinito su un modello) vengono utilizzati quando si selezionano i dati di output, anche se non sono altrimenti specificati in values()
chiamata. Questi campi aggiuntivi vengono utilizzati per raggruppare i risultati "mi piace" e possono far sembrare separate righe di risultati altrimenti identiche.
Se non sei sicuro, puoi semplicemente aggiungere il vuoto order_by()
clausola comunque senza effetti negativi.
cioè
from django.db.models import Sum
summary = (Invoice.objects
.annotate(m=Month('date'))
.values('m')
.annotate(total=Sum('total'))
.order_by())
Vedi il succo completo qui:https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17
Se hai bisogno di ulteriori informazioni:
Dettagli sulla creazione delle tue classi Func:https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions
Dettagli sulla clausola values(), (attenzione a come interagisce con annotate() rispetto all'ordine delle clausole):https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values
l'ordine in cui le clausole annotate() e values() vengono applicate a una query è significativo. Se la clausola values() precede annotate(), l'annotazione verrà calcolata utilizzando il raggruppamento descritto dalla clausola values().