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 de:
- Combien de ventes il y a eu en un mois (
COUNT
) - La valeur combinée (
SUM
)
Je ne sais pas quelle est la meilleure façon d'attaquer cela. J'ai vu des requêtes extra-sélectives assez effrayantes, mais mon esprit simple me dit que je ferais peut-être mieux d'itérer des nombres, en commençant par une année / mois de début arbitraire et en comptant jusqu'à ce que j'atteigne le mois en cours, en jetant simplement filtrage des requêtes pour ce mois. Plus de travail sur la base de données - moins de stress pour les développeurs!
Qu'est-ce qui a le plus de sens pour vous? Existe-t-il une bonne façon de récupérer un tableau rapide de données? Ou est-ce que ma méthode sale est probablement la meilleure idée?
J'utilise Django 1.3. Je ne sais pas s'ils ont ajouté une manière plus agréable GROUP_BY
récemment.
Réponses:
Django 1.10 et supérieur
Listes de documentation Django
extra
comme bientôt plus . (Merci de l'avoir signalé @seddonym, @ Lucas03). J'ai ouvert un ticket et c'est la solution fournie par jarshwah.Versions plus anciennes
Modifications
la source
>>> qs.extra({'month':td}).values('month').annotate(Sum('total')) [{'total__sum': Decimal('1234.56'), 'month': datetime.datetime(2011, 12, 1, 0, 0)}]
'{}.timestamp'.format(model._meta.db_table)
USE_TZ
paramètre Django estTrue
, les deux versions ne sont pas exactement équivalentes. La version utilisantTruncMonth
convertira l'horodatage dans le fuseau horaire spécifié par leTIME_ZONE
paramètre avant de tronquer, tandis que la version utilisantdate_trunc_sql
tronquera l'horodatage UTC brut dans la base de données.Juste un petit ajout à la réponse @tback: cela n'a pas fonctionné pour moi avec Django 1.10.6 et postgres. J'ai ajouté order_by () à la fin pour le réparer.
la source
TruncDate
vous permet de regrouper par date (jour du mois)Une autre approche consiste à utiliser
ExtractMonth
. J'ai rencontré des problèmes lors de l'utilisation de TruncMonth en raison du retour d'une seule valeur d'année datetime. Par exemple, seuls les mois de 2009 ont été renvoyés. ExtractMonth a parfaitement résolu ce problème et peut être utilisé comme ci-dessous:la source
Il
queryset
s'agit d'une liste de commandes, une ligne par mois, combinant la somme des ventes:sales_sum
@Django 2.1.7
la source
Voici ma sale méthode. C'est sale.
Il y a peut-être un meilleur moyen de boucler des années / mois mais ce n'est pas vraiment ce qui m'importe :)
la source
Voici comment regrouper les données par périodes de temps arbitraires:
la source
Par mois:
Par année:
De jour:
N'oubliez pas d'importer Count
Pour django <1.10
la source