2010-08-22 11 views
15

Ho un modello molto di base:Django annotare i raggruppamenti per mese

class Link(models.Model): 
    title = models.CharField(max_length=250, null=False) 
    user = models.ForeignKey(User) 
    url = models.CharField(max_length=250, blank=True, null=True) 
    link_count = models.IntegerField(default=0) 
    pub_date = models.DateField(auto_now_add=True) 
    updated = models.DateTimeField(auto_now=True) 

posso creare una lista di tutte le voci raggruppate per data utilizzando:

Link.objects.values('pub_date').order_by('-pub_date').annotate(dcount=Count('pub_date')) 

Questo, naturalmente, raggruppare gli elementi per giorno . Ma quello che voglio davvero è raggruppare per mese. C'è comunque che posso farlo usando annotate()?

Molte grazie,

G

+0

Non è una risposta, ma si potrebbe prendere un aspetto a questo biglietto: http://code.djangoproject.com/ticket/10302 –

+0

ciò che è 'CONTO'? –

risposta

15

Se siete su PostgreSQL, il seguente potrebbe funzionare:

from django.db.models import Count 

Link.objects.extra(select={'month': 'extract(month from pub_date)'}).values('month').annotate(dcount=Count('pub_date')) 

io non sono sicuro di come portatile extract è attraverso altri database.

+0

Grazie! Questo sembra funzionare anche per mySQL. Tranne questo raggruppa tutti i mesi attraverso qualsiasi anno. Sto cercando di ottenere mesi raggruppati per ogni anno. Ma questo è un ottimo inizio, quindi ottimizzerò. Grazie ancora. – givp

+0

puoi schiaffeggiare un filtro lì che limita le date a determinati intervalli. '.filter (pub_date__gte = datetime.datetime (compila data qui))' – boatcoder

+4

usando 'connection.ops.date_trunc_sql ('month', 'date')' invece di estratto hardcoded SQL renderebbe l'istruzione compatibile con altri backend – jujule

13
from django.db import connections 
from django.db.models import Count 

Link.objects.extra(select={'month': connections[Link.objects.db].ops.date_trunc_sql('month', 'pub_date')}).values('month').annotate(dcount=Count('pub_date')) 
+1

Nota che devi importare anche da django.db.models import Count –

3

Per aggiungere, come alternativa per l'utilizzo di extra(): dal Django 1.8, è anche possibile utilizzare espressioni condizionali.

>>> year_overview = Link.objects.filter(pub_date__year=year).aggregate(
    jan=Sum(
     Case(When(created__month=0, then=1), 
      output_field=IntegerField()) 
    ), 
    feb=Sum(
     Case(When(created__month=1, then=1), 
      output_field=IntegerField()) 
    ), 
    mar=Sum(
     Case(When(created__month=2, then=1), 
      output_field=IntegerField()) 
    ), 
    apr=Sum(
     Case(When(created__month=3, then=1), 
      output_field=IntegerField()) 
    ), 
    may=Sum(
     Case(When(created__month=4, then=1), 
      output_field=IntegerField()) 
    ), 
    jun=Sum(
     Case(When(created__month=5, then=1), 
      output_field=IntegerField()) 
    ), 
    jul=Sum(
     Case(When(created__month=6, then=1), 
      output_field=IntegerField()) 
    ), 
    aug=Sum(
     Case(When(created__month=7, then=1), 
      output_field=IntegerField()) 
    ), 
    sep=Sum(
     Case(When(created__month=8, then=1), 
      output_field=IntegerField()) 
    ), 
    oct=Sum(
     Case(When(created__month=9, then=1), 
      output_field=IntegerField()) 
    ), 
    nov=Sum(
     Case(When(created__month=10, then=1), 
      output_field=IntegerField()) 
    ), 
    dec=Sum(
     Case(When(created__month=11, then=1), 
      output_field=IntegerField()) 
    ), 
) 

>>> year_overview 
{'mar': None, 'feb': None, 'aug': None, 'sep': 95, 'apr': 1, 'jun': None, 'jul': None, 'jan': None, 'may': None, 'nov': 87, 'dec': 94, 'oct': 100} 
+2

Con l'ultima versione di Django immagino che questa sia la soluzione raccomandata –

2

Ho letto che .extra() verrà ritirato in futuro. Stanno suggerendo di utilizzare invece gli oggetti Func. E ce n'è uno per estrarre un mese senza usare una dolorosa affermazione Case.

from django.db.models.functions import ExtractMonth 
Link.objects.all().annotate(pub_date_month=ExtractMonth('pub_date')) 
Problemi correlati