Frage

Ich habe eine Reihe von Objekten, die einen Wert und ein Datumsfeld haben:

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

Ich möchte diese zurückgegeben:

[10, 15, 0, 8]

oder besser noch, ein Aggregat der Gesamt bis zu diesem Punkt:

[10, 25, 25, 33]

Ich wäre am besten, diese Daten direkt aus der Datenbank zu bekommen, aber sonst kann ich die Höhe von ziemlich leicht mit einem forloop tun.

Ich bin mit Django ORM und auch Postgres

edit:

Just zu beachten, dass mein Beispiel nur ein paar Tage bedeckt, aber in der Praxis, ich habe Hunderte von Objekten ein paar Jahrzehnte abdeckt ... Was ich versuche ein Liniendiagramm zu tun ist, erstellen die zeigt, wie die Summe aller meine Objekte haben im Laufe der Zeit (eine sehr lange Zeit)

gewachsen
War es hilfreich?

Lösung

Dieses ist nicht getestet, da es ein bisschen zu viel Schmerz ein Django-Tabelle Test einzurichten mit:

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)]

Dadurch wird eine separate Abfrage für jeden Tag ausgeführt wird.

Andere Tipps

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

Wenn Sie mehr als ein Obj pro Tag haben, müssen Sie Len (obj) überprüfen und Iterierte über sie, falls es mehr als 1 ist.

Wenn Sie eine Schleife durch ein Obj.objects.get 100 mal, Sie tun 100 SQL-Abfragen. Obj.objects.filter werden die Ergebnisse in einer SQL-Abfrage zurück, sondern Sie auch alle Modellfelder auswählen. Der richtige Weg, dies zu tun ist Obj.objects.values_list zu verwenden, die dies mit einer einzigen Abfrage zu tun, und wählen Sie nur das Feld ‚Werte‘.

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]

ein laufendes Aggregat von val_list zu tun, können Sie diese (nicht sicher, dass dies die Art und Weise pythonic ist) tun

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: Wenn Sie Konto benötigen Tage fehlen, Antwort @Glenn Maynards ist eigentlich ziemlich gut, obwohl ich es vorziehen, die dict () Syntax:

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]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top