2010-08-31 98 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