Domanda

Ho un sacco di oggetti che hanno un valore e un campo data:

obj1 = Obj(date='2009-8-20', value=10)
obj2 = Obj(date='2009-8-21', value=15)
obj3 = Obj(date='2009-8-23', value=8)

Voglio che questo restituito:

[10, 15, 0, 8]

o meglio ancora, un aggregato del totale fino a quel momento:

[10, 25, 25, 33]

Vorrei essere meglio per ottenere questi dati direttamente dal database, ma per il resto non posso fare il totale abbastanza facilmente con un forloop.

Sto usando ORM di Django e anche Postgres

modifica:

Basta notare che il mio esempio copre solo un paio di giorni, ma in pratica, ho centinaia di oggetti che coprono un paio di decenni ... Quello che sto cercando di fare è creare un grafico a linee che mostra come la somma di tutti miei oggetti è cresciuta nel tempo (un tempo molto lungo)

È stato utile?

Soluzione

Questo non è testato, dal momento che è un po 'troppo di un dolore di istituire un tavolo Django per testare con:

from datetime import date, timedelta
# http://www.ianlewis.org/en/python-date-range-iterator
def datetimeRange(from_date, to_date=None):
    while to_date is None or from_date <= to_date:
        yield from_date
        from_date = from_date + timedelta(days = 1)

start = date(2009, 8, 20)
end = date(2009, 8, 23)
objects = Obj.objects.filter(date__gte=start)
objects = objects.filter(date__lte=end)

results = {}
for o in objects:
    results[o.date] = o.value

return [results.get(day, 0) for day in datetimeRange(start, end)]

Questo consente di evitare l'esecuzione di una query separata per ogni giorno.

Altri suggerimenti

result_list = []
for day in range(20,24):    
    result = Obj.objects.get(date=datetime(2009, 08, day))
    if result:
        result_list.append(result.value)
    else:
        result_list.append(0)
return result_list

Se si dispone di più di un Obj per ogni data, è necessario controllare len (obj) e scorrere su di loro nel caso si tratta di più di 1.

Se ciclo attraverso un Obj.objects.get 100 volte, che stai facendo 100 query SQL. Obj.objects.filter restituirà i risultati in una query SQL, ma anche selezionare tutti i campi del modello. Il modo giusto per farlo è quello di utilizzare Obj.objects.values_list, che fare questo con una singola query, e selezionare solo il campo 'valori'.

start_date = date(2009, 8, 20)
end_date = date(2009, 8, 23)

objects = Obj.objects.filter(date__range=(start_date,end_date))
# values_list and 'value' aren't related. 'value' should be whatever field you're querying
val_list = objects.values_list('value',flat=True)
# val_list = [10, 15, 8]

Per fare un aggregato in esecuzione di val_list, si può fare questo (non certo che questo è il modo più divinatorio)

for i in xrange(len(val_list)):
    if i > 0:
        val_list[i] = val_list[i] + val_list[i-1]

# val_list = [10,25,33]

EDIT: Se è necessario tenere conto di giorni mancanti, la risposta di @Glenn Maynard è in realtà piuttosto buono, anche se io preferisco la sintassi dict ():

objects = Obj.objects.filter(date__range=(start_date,end_date)).values('date','value')
val_dict = dict((obj['date'],obj['value']) for obj in objects)
# I'm stealing datetimeRange from @Glenn Maynard
val_list = [val_dict.get(day, 0) for day in datetimeRange(start_date, end_date)]
# val_list = [10,15,0,8]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top