2009-09-03 67 views
1

我有一堆有一个值和日期字段对象:查询基于数据/ Django的ORM

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

我想这回:

[10, 15, 0, 8] 

或更好,总的到这一点,合计:

[10, 25, 25, 33] 

我最好的办法是直接从数据库中获取这个数据,但否则我使用forloop可以很轻松地完成总计。

我使用Django的ORM,也Postgres的

编辑:

只是要注意,我的例子只覆盖了几天,但在实践中,我有上百个涵盖了几十年的对象。 ..我想要做的就是创建一个线图显示我的所有对象的总和如何在持续增长(很长的时间)

+0

数据库?什么数据库?直到我们完成并在标签中看到您使用的是Django(因此推测是它的内置ORM - 如果您使用的是另一种,您应该指定!),但这个问题非常混乱;未来,请将这些信息放在主题中或其他前面。我在这里做了适当的编辑。 – 2009-09-03 03:51:49

+0

woops,对不起。是的,我正在使用django ORM,我也在使用Postgres – priestc 2009-09-03 04:46:04

+0

我们可以假设每个日期只有一个或零个对象吗? – Wogan 2009-09-03 09:05:37

回答

4

这一个是没有经过测试,因为这是一个有点太痛苦成立一个Django表来测试:

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

这避免了运行,每天一个单独的查询。

+0

Django查询集被懒惰地评估,所以你实际上最终每天都会运行一个单独的查询。 – David 2009-09-03 08:52:42

+1

除了这里的查询集只被评估一次,在for循环的开始,所以没关系。 – Wogan 2009-09-03 09:03:54

+0

每次调用o.value时,都会触及数据库,因此每天都会触击数据库。 – David 2009-09-03 09:10:42

0
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 

如果每个日期有一个以上的OBJ,你需要检查len(obj)并在它超过1时迭代它们。

0

如果您循环访问100次Obj.objects.get,则会执行100次SQL查询。 Obj.objects.filter将在一个SQL查询中返回结果,但您也选择所有模型字段。这样做的正确方法是使用Obj.objects.values_list,它将使用单个查询来完成此操作,并仅选择“值”字段。

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] 

做val_list的运行聚合,你可以做到这一点(不能确定这是最Python的方式)

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] 

编辑:如果您需要考虑失踪天,@Glenn Maynard的答案其实很不错,尽管我更喜欢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] 
+0

此答案未能为数据库中不存在的天提供值。 – Wogan 2009-09-03 09:04:39

+1

-1对我的解决方案做出虚假陈述,然后给出与我完全相同的解决方案(但以不太清楚的方式)。 – 2009-09-03 19:00:40

+0

当我写这篇文章的时候,我不清楚DB会缺少日期。你是对的,如果数据库缺少日期,那么你的解决方案是好的。 – David 2009-09-03 19:15:48