2012-02-26 52 views
7

在我的Django模型,我有代表一个事件的单次发生一个非常简单的模型(如服务器警报发生):分组按周,并填充了“失踪”周

class EventOccurrence: 
    event = models.ForeignKey(Event) 
    time = models.DateTimeField() 

我的最终目标是制作一个表格或图表,显示过去几星期发生事件的次数。

所以我的问题有两个部分:

  • 我怎样才能group_bytime领域的一周?
  • 我怎样才能“拉长”这group_by的结果对于任何缺失周增加一个零值?

例如,对于第二部分,我想改变这样的结果:

| week | count |     | week | count | 
| 2 | 3  |     | 2 | 3  | 
| 3 | 5  | —— becomes —> | 3 | 5  | 
| 5 | 1  |     | 4 | 0  | 
            | 5 | 1  | 

什么是Django中做到这一点的最好方法是什么?一般的Python解决方案也可以。

回答

4

Django的DateField以及datetime不支持一周属性。要在一个查询中获取一切,你需要做的:

from django.db import connection 

cursor = connection.cursor() 
cursor.execute(" SELECT WEEK(`time`) AS 'week', COUNT(*) AS 'count' FROM %s GROUP BY WEEK(`time`) ORDER BY WEEK(`time`)" % EventOccurrence._meta.db_table, []) 

data = [] 
results = cursor.fetchall() 
for i, row in enumerate(results[:-1]): 
    data.append(row) 

    week = row[0] + 1 
    next_week = results[i+1][0] 
    while week < next_week: 
     data.append((week, 0)) 
     week += 1 
data.append(results[-1]) 

print data 
0

挖Django的查询API文档后,我还没有找到一种方法,使通过Django的ORM系统查询。 Cursor是一个解决办法,如果你的数据库的品牌是MySQL的:

from django.db import connection, transaction 
cursor = connection.cursor() 

cursor.execute(""" 
    select 
     week(time) as `week`, 
     count(*) as `count` 
    from EventOccurrence 
    group by week(time) 
    order by 1;""") 

myData = dictfetchall(cursor) 

这一点,在我看来,表现最好的解决方案。但请注意,这不会弥补失踪周。

EDITED通过Python(性能较低)

上独立的数据库解决方案的品牌。如果你正在寻找的数据库品牌独立代码,那么你应该采取的日期一天天和通过Python聚集它。如果这是你的情况下,代码可能看起来像:

#get all weeks: 
import datetime 
weeks = set() 
d7 = datetime.timedelta(days = 7) 
iterDay = datetime.date(2012,1,1) 
while iterDay <= datetime.now(): 
    weeks.add(iterDay.isocalendar()[1]) 
    iterDay += d7 

#get all events 
allEvents = EventOccurrence.objects.value_list('time', flat=True) 

#aggregate event by week 
result = dict() 
for w in weeks: 
    result.setdefault(w ,0) 

for e in allEvents: 
    result[ e.isocalendar()[1] ] += 1 

(免责声明:未测试)

0

因为我要查询的投身其中多个表,我使用的数据库视图来解决这些需求。

CREATE VIEW my_view 
    AS 
    SELECT 
    *, // <-- other fields goes here 
    YEAR(time_field) as year, 
    WEEK(time_field) as week 
    FROM my_table; 

和模型:从这个数据库视图获取行,由@danihp使用的方式来填充0“洞”周/数月后

from django.db import models 

class MyView(models.Model): 
    # other fields goes here 
    year = models.IntegerField() 
    week = models.IntegerField() 

    class Meta: 
     managed = False 
     db_table = 'my_view' 

    def query(): 
     rows = MyView.objects.filter(week__range=[2, 5]) 
     # to handle the rows 

注意:这仅仅是测试MySQL后台,我不知道这是否是对MS SQL Server或其他确定。