Nejprve musíte vytvořit funkci, která za vás může extrahovat měsíc:
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()
Poté vše, co musíte udělat, je
- každý řádek označte měsícem
- seskupte výsledky podle anotovaného měsíce pomocí
values()
- každý výsledek označte agregovaným součtem součtů pomocí
Sum()
Důležité :pokud má vaše modelová třída výchozí řazení specifikované v možnostech metadat, budete muset přidat prázdné order_by()
doložka. Důvodem je https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by
Pole, která jsou zmíněna v
order_by()
část sady dotazů (nebo které se používají ve výchozím uspořádání na modelu) se používají při výběru výstupních dat, i když nejsou jinak specifikována vvalues()
volání. Tato doplňková pole se používají k seskupování výsledků „líbí se“ a mohou způsobit, že jinak identické řádky výsledků vypadají jako samostatné.
Pokud si nejste jisti, můžete přidat prázdné order_by()
klauzule každopádně bez jakýchkoli nepříznivých účinků.
tj.
from django.db.models import Sum
summary = (Invoice.objects
.annotate(m=Month('date'))
.values('m')
.annotate(total=Sum('total'))
.order_by())
Podívejte se na úplný obsah zde:https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17
Pokud potřebujete další informace:
Podrobnosti o vytváření vlastních tříd Func:https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions
Podrobnosti o klauzuli values() (věnujte pozornost tomu, jak interaguje s anotate() s ohledem na pořadí klauzulí):https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values
důležité je pořadí, ve kterém jsou klauzule annotate() a values() aplikovány na dotaz. Pokud klauzule values() předchází anotate(), bude anotace vypočítána pomocí seskupení popsaného v klauzuli values().