2011-04-19 74 views
4

我有一個記錄集,看起來像這樣(多餘的數據忽略,以保護容易厭煩):Can Django的.annotate()可以返回對象嗎?

id | user_id |   created   | units 
----+---------+-------------------------------+------- 
    1 |  1 | 2011-04-18 15:43:02.737063+00 | 20 
    2 |  1 | 2011-04-18 15:43:02.737063+00 |  4 
    3 |  1 | 2011-04-18 15:46:48.592999+00 | -1 
    4 |  1 | 2011-04-19 12:02:10.687587+00 | -1 
    5 |  1 | 2011-04-19 12:09:20.039543+00 | -1 
    6 |  1 | 2011-04-19 12:11:21.948494+00 | -1 
    7 |  1 | 2011-04-19 12:15:51.544394+00 | -1 
    8 |  1 | 2011-04-19 12:16:44.623655+00 | -1 

而且我想獲得的結果,看起來像這樣:

id | user_id |   created   | units 
----+---------+-------------------------------+------- 
    8 |  1 | 2011-04-19 12:16:44.623655+00 | 14 
    2 |  1 | 2011-04-18 15:43:02.737063+00 |  4 

所以我很自然地看向.annotate()

u = User.objects.get(pk=1) 
(MyModel.objects.filter(user=u) 
     .values("id","user","created") 
     .annotate(stuff=Sum("units")) 
) 

的問題是,我想對象,不是一個單一的字典列表。我需要附加到這些對象的方法才能使用。任何想法如何做到這一點?

編輯: 我應該指出,我嘗試使用.values(),因爲沒有它,我會得到一堆標註對象的還好,但會有其中8個(如在第一次查詢以上) ,而不是2(如上面的第二個結果)。我的猜測是因爲有一個時間戳它沒有結合排在那裏做行不同:

MyModel.objects.filter(user=u).annotate(Sum("units")) 
# Returns 8 records, not 2 as expected 
+1

對於問題的第二部分,註釋,我m沒有看到第一組數據如何導致第二組數據... 爲什麼ids 8和2剩下的總數是14和4? 註釋不會減少返回的行數。 也許,如果你添加了SQL,你正在嘗試查看 – Chris 2011-04-20 09:01:34

+0

什麼是你用於生成結果表(2行)上面顯示的正常sql查詢 – 2011-04-20 12:43:15

回答

5

當我最初提出問題時,看起來有些困惑,結果我被指示不使用.values(),但實際上並沒有問題。問題是Django的.annotate()不允許使用計算值覆蓋列屬性,並且只能用附加數據註釋對象。這很有意義,因爲如果你想返回一個對象,你希望能夠假設所討論的對象實際上代表了數據庫中的一行,而不是覆蓋列值的混雜計算值。

但是,這並沒有爲我工作,因爲上述功能意味着像created(時間戳)這樣的列,你不能得到我想要的計算值,而不使用.values() ......並沒有給出我反對。

所以,我選擇了退而求其次:.raw()

query = """ 
    SELECT 
     ep.product_id    AS product_id, 
     ep.user_id     AS user_id, 
     MAX(ep.created)   AS created, 
     SUM(eup.units)    AS units 
    FROM 
     ecom_unitpermission AS eup 
    WHERE 
     ep.user_id = 1 
    GROUP BY 
     ep.product_id, 
     ep.user_id 
""" 

for perm in MyModel.objects.raw(query): 
    print "%15s %3s %s" % (perm.product.name, perm.units, perm.product.somemethod()) 

使用.defer()可能已經做到了這一點對我來說,雖然there appears to be a bug in Django 1.3 when combining that with .annotate()

3

這個問題不註釋,但調用的值。 documentation很清楚地表明註釋在查詢集上起作用。這是值調用返回值的字典,並使您失去訪問模型的能力。

編輯補充:如果你只是想帶回某些領域,但仍然有模型,然後使用defer不是值

+0

其實,我補充說。values()因爲沒有它,我無法得到結果聚合到我預期的兩行。我認爲這與我在那裏有一個時間戳的事實有關,所以行都是不同的。 – 2011-04-19 15:04:05

0

註釋返回的查詢集的,但你還呼籲.values(),這將始終回報一本字典。

相關問題