2012-02-26 55 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或其他確定。