2010-08-31 54 views
4

我得到了一個簡單的要求(不是簡單的實現),並找出瞭如何實現它,而無需在db中創建多個命中,並且在queryset中沒有.extra()Django中的條件註釋

Task: 
    name = xxx 
    status = models.IntegerField(choices=some_choices) 
    project = ForeignKey(Project) 

Project: 
    name = xxx 
    code = xxx 

項目包含具有各種狀態的任務。 (假設狀態= 3已完成) 現在,我想列出與他們的總任務和完成任務的所有項目,如下面

  1. 項目1項,total_tasks = 5,completed_tasks = 2
  2. 項目1項, total_tasks = 2,completed_tasks = 1

我能夠獲得與註釋total_tasks,但不completed_tasks,因爲它在標註要求的條件。無論如何去做?

+0

你會如何計劃使用原始SQL做到這一點呢? – 2010-08-31 09:29:23

+1

http://stackoverflow.com/questions/2875122/django-and-conditional-aggregates – 2010-08-31 09:33:14

+0

+1。很顯然,這種功能在覈心中並不存在。但是,有什麼辦法可以使用F()等來實現它? – 2010-08-31 09:46:46

回答

0

我不知道它是否會有幫助,但您可以編寫自己的自定義註釋對象。雖然沒有條件部分,但我已經完成了。我基於我的解決方案在這個鏈接: http://www.voteruniverse.com/Members/jlantz/blog/conditional-aggregates-in-django

但沒有使用那裏的例子。相反,我查看了聚合的django代碼,並自己擴展了Sum和Count對象。

+0

不確定鏈接的博客是暫時還是永久停用,但無論如何這裏都有一個存檔版本:http://web.archive.org/web/20101115170804/http://www.voteruniverse.com/Members/jlantz/blog/conditional-aggregates-in-django – 2012-05-18 06:53:23

0

如果您不介意其他查詢,則可以派生兩個查詢集而不是一個查詢集。第一個可以讓你的總數,第二個可以過濾tasks_status,從而讓你完成計數。

from django.db.models import Count 
all_projects = Project.objects.all() 
total_counts = all_projects.annotate(count = Count('tasks')) 
completed_counts = all_projects.filter(tasks_status = 3).annotate(count = Count('tasks')) 
+0

這比我的蠻力方法好一些,我在迭代所有項目和附加查詢集以獲得completed_counts。 但是,它再次迫使我們匹配項目vs completed_counts,可能在模板或查看 – 2010-08-31 09:52:42

+0

同意。您必須在模板或視圖中將項目與計數匹配。 – 2010-08-31 10:14:57

5

此功能是新的Django 1.8。

參考:https://docs.djangoproject.com/en/1.8/ref/models/conditional-expressions/

這是一個可能性:

from django.db.models.aggregates import Count 
from django.db.models.expressions import F, Value, Case, When 

projects = Project.objects.annotate(
     total_tasks=Count('task__pk'), 
     completed_tasks=Count(Case(
      When(status=3, then=F('task__pk')), 
      output_field=IntegerField() 
     ))).all() 
+0

美麗!非常好的更新答案,謝謝。應該在「Count」文檔中 – 2017-10-03 17:39:56