Tout d'abord, vous devez créer une fonction qui peut extraire le mois pour vous :
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()
Après cela, tout ce que vous avez à faire est
- annotez chaque ligne avec le mois
- regrouper les résultats par mois annoté en utilisant
values()
- annotez chaque résultat avec la somme agrégée des totaux en utilisant
Sum()
Important :si votre classe de modèle a un ordre par défaut spécifié dans les options méta, alors vous devrez ajouter un order_by()
vide clause. C'est à cause de https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by
Champs mentionnés dans le
order_by()
partie d'un ensemble de requêtes (ou qui sont utilisées dans l'ordre par défaut sur un modèle) sont utilisées lors de la sélection des données de sortie, même si elles ne sont pas autrement spécifiées dans levalues()
appel. Ces champs supplémentaires sont utilisés pour regrouper les résultats "similaires" et ils peuvent faire apparaître des lignes de résultats par ailleurs identiques comme étant séparées.
Si vous n'êtes pas sûr, vous pouvez simplement ajouter le vide order_by()
clause de toute façon sans aucun effet indésirable.
c'est-à-dire
from django.db.models import Sum
summary = (Invoice.objects
.annotate(m=Month('date'))
.values('m')
.annotate(total=Sum('total'))
.order_by())
Voir l'essentiel ici :https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17
Si vous avez besoin de plus d'informations :
Détails sur la création de vos propres classes Func :https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions
Détails sur la clause values(), (faites attention à la façon dont elle interagit avec annotate() par rapport à l'ordre des clauses) :https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values
l'ordre dans lequel les clauses annotate() et values() sont appliquées à une requête est important. Si la clause values() précède annotate(), l'annotation sera calculée à l'aide du regroupement décrit par la clause values().