Pregunta

Tengo un montón de objetos que tienen un valor y un campo de fecha:

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

Quiero que este regresó:

[10, 15, 0, 8]

o mejor aún, un agregado del total hasta ese momento:

[10, 25, 25, 33]

Yo sería la mejor manera de obtener estos datos directamente de la base de datos, pero por lo demás que pueda hacer el total con bastante facilidad con un forloop.

Estoy usando ORM de Django y Postgres

editar

Sólo tener en cuenta, que mi ejemplo sólo cubre unos pocos días, pero en la práctica, tengo cientos de objetos que cubren un par de décadas ... Lo que estoy tratando de hacer es crear un gráfico lineal que muestra cómo la suma de todos mis objetos ha crecido con el tiempo (mucho tiempo)

¿Fue útil?

Solución

Éste no es probado, ya que es un poco demasiado de un dolor para establecer una mesa de Django para probar 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)]

Esto evita ejecución de una consulta separada para cada día.

Otros consejos

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

Si usted tiene más de un obj por fecha, tendrá que comprobar len (obj) e iterar sobre ellos en caso de que sea más de 1.

Si un bucle a través de Obj.objects.get 100 veces, lo estás haciendo 100 consultas SQL. Obj.objects.filter devolverá los resultados de una consulta SQL, pero también seleccionar todos los campos del modelo. La forma correcta de hacer esto es utilizar Obj.objects.values_list, que va a hacer esto con una sola consulta, y sólo seleccionar el campo de 'valores'.

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]

Para realizar una agregación acumulativa de val_list, usted puede hacer esto (no seguro de que esta es la manera más Pythonic)

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: Si usted necesita para tener en cuenta los días que faltan, la respuesta de @Glenn Maynard es realmente muy bueno, aunque prefiero la sintaxis 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]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top