120 votes

Django : Grouper par date (jour, mois, année)

J'ai un modèle simple comme celui-ci :

class Order(models.Model):
    created = model.DateTimeField(auto_now_add=True)
    total = models.IntegerField() # monetary value

Et je veux produire une ventilation mois par mois :

  • Combien de ventes ont été réalisées en un mois ( COUNT )
  • La valeur combinée ( SUM )

Je ne sais pas quelle est la meilleure façon d'aborder cette question. J'ai vu des requêtes extra-sélectives assez effrayantes, mais mon esprit simple me dit que je ferais mieux d'itérer des nombres, en commençant par une année/mois arbitraire et en comptant jusqu'au mois en cours, en lançant des requêtes simples filtrant pour ce mois. Plus de travail sur la base de données - moins de stress pour le développeur !

Qu'est-ce qui vous semble le plus logique ? Existe-t-il un moyen efficace de récupérer rapidement un tableau de données ? Ou bien ma sale méthode est-elle probablement la meilleure idée ?

J'utilise Django 1.3. Je ne sais pas s'ils ont ajouté une façon plus agréable d'utiliser la fonction GROUP_BY récemment.

1voto

jatinkumar patel Points 2574

Par mois :

 Order.objects.filter().extra({'month':"Extract(month from created)"}).values_list('month').annotate(Count('id'))

Par année :

 Order.objects.filter().extra({'year':"Extract(year from created)"}).values_list('year').annotate(Count('id'))

De jour :

 Order.objects.filter().extra({'day':"Extract(day from created)"}).values_list('day').annotate(Count('id'))

N'oubliez pas d'importer le comte

from django.db.models import Count

Pour django < 1.10

1voto

Shemhamforasch Points 153

Voici comment vous pouvez regrouper des données par périodes de temps arbitraires :

from django.db.models import F, Sum
from django.db.models.functions import Extract, Cast
period_length = 60*15 # 15 minutes

# Annotate each order with a "period"
qs = Order.objects.annotate(
    timestamp=Cast(Extract('date', 'epoch'), models.IntegerField()),
    period=(F('timestamp') / period_length) * period_length,
)

# Group orders by period & calculate sum of totals for each period
qs.values('period').annotate(total=Sum(field))

0voto

Sarath Chandran K Points 111

J'ai une table de commandes dans ma base de données. Je vais compter les commandes par mois au cours des 3 derniers mois.

from itertools import groupby
from dateutil.relativedelta import relativedelta

date_range = datetime.now()-relativedelta(months=3)
aggs =Orders.objects.filter(created_at=date_range)\
            .extra({'date_created':"date(created_at)"}).values('date_created')

for key , group in groupby(aggs):
     print(key,len(list(group)))

created_at est un champ de type datetime. Cette fonction supplémentaire permet d'extraire la date des valeurs datetime. Lorsque l'on utilise la datetime, il se peut que le décompte ne soit pas correct car les objets sont créés à différents moments de la journée.

La boucle for imprimera la date et le nombre de comptages.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X