Question

J'ai un tas d'objets qui ont une valeur et un champ de date:

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

Je veux que ce retour:

[10, 15, 0, 8]

ou mieux encore, un agrégat du total jusqu'à ce point:

[10, 25, 25, 33]

Je serais mieux pour obtenir ces données directement à partir de la base de données, mais sinon je peux faire le montant total assez facilement avec un forloop.

J'utilise ORM de Django et aussi Postgres

edit:

Il suffit de noter que mon exemple ne couvre que quelques jours, mais en pratique, j'avoir des centaines d'objets couvrant quelques décennies ... Ce que je suis en train de faire est de créer un graphique linéaire montrant comment la somme de tous mes objets a augmenté au fil du temps (un temps très long)

Était-ce utile?

La solution

Celui-ci n'a pas été testé, car il est un peu trop d'une douleur à mettre en place une table Django pour tester avec:

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

Ceci permet d'éviter l'exécution d'une requête distincte pour chaque jour.

Autres conseils

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 vous avez plus d'un Obj par jour, vous aurez besoin de vérifier len (obj) et itérer sur eux dans le cas où il est plus que 1.

Si vous boucle à travers un Obj.objects.get 100 fois, vous faites 100 requêtes SQL. Obj.objects.filter renverra les résultats dans une requête SQL, mais vous aussi sélectionner tous les champs du modèle. La bonne façon de le faire est d'utiliser Obj.objects.values_list, qui le fera avec une seule requête, et seulement sélectionner le champ « valeurs ».

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]

Pour un total en cours d'exécution de val_list, vous pouvez le faire (pas certain que ce soit la façon la plus pythonique)

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 vous devez tenir compte des jours manquants, la réponse de @Glenn Maynard est en fait assez bien, même si je préfère la syntaxe 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]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top