2011-08-09 106 views
8

我很驚訝,這個問題顯然還不存在。如果是這樣,請幫我找到它。Django條件註釋

我想使用annotate(Count)和order_by,但我不想計算相關對象的每個實例,只有那些符合某個標準的對象。

要機智,我可能會被綠色的椰子數量列出燕子他們進行:

swallow.objects.annotate(num_coconuts=Count('coconuts_carried__husk__color = "green"').order_by('num_coconuts') 

回答

8

這應該是正確的方式。

swallow.objects.filter(
    coconuts_carried__husk__color="green" 
).annotate(
    num_coconuts=Count('coconuts_carried') 
).order_by('num_coconuts') 

請注意,當您篩選相關字段時,在原始SQL中,它將轉換爲LEFT JOIN加上WHERE。最後,註釋將作用於結果集,結果集僅包含從第一個過濾器中選擇的相關行。

+0

事實上,這似乎工作,但對於你所指出的原因,這是完全反直覺。我希望這個查詢集能夠給我所有曾經攜帶過至少一顆綠椰子的燕子,按照不論顏色攜帶的椰子總數排序。 – jMyles

+1

@jMyles:文檔指出,這取決於[順序註釋和濾波器條款(https://docs.djangoproject.com/en/1.3/topics/db/aggregation/#order-of-annotate-上和過濾器子句) - 反過來說,它會像你描述的那樣行事。 –

+2

如果你想包括那些沒有攜帶綠色椰子的燕子呢? –

3

Django的> = 1.8:

from django.db.models import Sum, Case, When, IntegerField 

swallow.objects.annotate(
    num_coconuts=Sum(Case(
     When(coconuts_carried__husk__color="green", then=1), 
     output_field=IntegerField(), 
    )) 
).order_by('num_coconuts')