2011-06-22 74 views
5

所以我有一组可以出现在许多类别的任务:在许多复杂的计数的许多领域在Django ORM

class TaskGroup(models.Model): 
    name = models.CharField(max_length=200) 
    slug = models.SlugField(max_length=200) 
    icon = models.CharField(max_length=200, blank=True, null=True) 

    def __unicode__(self): 
     return unicode(self.name) 


class Task(models.Model): 
    start_date = models.DateField() 
    end_date = models.DateField() 
    is_date_fuzzy = models.BooleanField() 
    name = models.CharField(max_length=200) 
    assignee = models.ForeignKey(User, verbose_name="users who is assigned the task", blank=True, null=True) 
    task_groups = models.ManyToManyField(TaskGroup) 

正如你所看到的,每个任务可以出现在多个任务组。

我想通过我的查询应满足以下条件:

  1. 所有TaskGroups的清单应 返回。
  2. 特定组内任务 的数量。即 家具(3),寝具(2)中,楼层 灯(6)
  3. 如果对于一个 特定任务组没有任务,所述基团 应该具有0
  4. 任务每个组内被 限于由当前用户。

我想出了迄今为止最好的是这样的:

TaskGroup.objects.filter(
    task__assignee=current_usr 
).annotate(
    task_count=Count('task__id') 
).order_by('name') 

但它做计数之前过滤一切,所以我没有看到任务组零级的任务。

也许我很想,但我一直试图做这个很长的时间,我在这个阶段只是试图循环,自己做数。

我真的希望你能帮助拯救我的理智的小遗迹!

回答

0

我有完全相同的问题一次。一种解决方案是使用额外的子查询:

TaskGroup.objects.extra(
    select={"task_count": "SELECT COUNT(*) from app_task where app_task.id=app_taskgroup.task_id AND app_task.assignee = '?'"}, 
    select_params = [current_usr] 
).order_by('name') 

或类似的东西。可能加入的关键是错误的。

但这只是丑陋的。并打破了很多DRY和DB独立原则。

更好的选择可能是使用2个查询。第二个对于不具有分配给该用户的任何任务的特殊群体:

empty_groups = TaskGroup.objects.exclude(task__assignee=current_usr) 

然后,只需遍历两套,而不是唯一的一个。

+0

谢谢,我可能只会使用包装在扩展管理器类中的原始SQL。非常沮丧的看到,因为这是一个非常明显的使用cas。也许我可以用第二种方式去做;这两个查询可以是分开的,因为我不需要它们成为同一个列表的一部分 - 最好在不同的列表中有未使用的TaskGroups(我仍然需要人们能够看到它们)。感谢编辑我的问题 - 我喜欢一点OCD整洁。 – pip