Najpierw musisz utworzyć funkcję, która może wyodrębnić miesiąc za Ciebie:
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()
Potem wszystko, co musisz zrobić, to
- dodaj do każdego wiersza miesiąc
- pogrupuj wyniki według miesiąca z adnotacjami za pomocą
values()
- Opisz każdy wynik zagregowaną sumą sum za pomocą
Sum()
Ważne :jeśli twoja klasa modelu ma domyślną kolejność określoną w opcjach meta, będziesz musiał dodać pusty order_by()
klauzula. Dzieje się tak z powodu https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by
Pola wymienione w order_by()
części zestawu zapytań (lub które są używane w domyślnej kolejności w modelu) są używane podczas wybierania danych wyjściowych, nawet jeśli nie są one inaczej określone w values()
połączenie. Te dodatkowe pola służą do grupowania „podobnych” wyników i mogą sprawić, że identyczne wiersze wyników będą wyglądać na oddzielne.
Jeśli nie masz pewności, możesz po prostu dodać pusty order_by()
klauzula mimo wszystko bez żadnych negatywnych skutków.
tj.
from django.db.models import Sum
summary = (Invoice.objects
.annotate(m=Month('date'))
.values('m')
.annotate(total=Sum('total'))
.order_by())
Zobacz pełny opis tutaj:https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17
Jeśli potrzebujesz więcej informacji:
Szczegóły dotyczące tworzenia własnych klas Func:https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions
Szczegóły dotyczące klauzuli values() (zwróć uwagę na to, jak współdziała z annotate() w odniesieniu do kolejności klauzul):https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values
kolejność, w jakiej klauzule annotate() i values() są stosowane do zapytania, jest istotna. Jeśli klauzula values() poprzedza annotate(), adnotacja zostanie obliczona przy użyciu grupowania opisanego w klauzuli values().