2012-10-20 71 views
0

我有两个型号,一个项目和行动:Django的查询

class Project(models.Model): 
    name = models.CharField("Project Name", max_length=200, unique = True) 

class Action(models.Model): 
    name = models.CharField("Action Name", max_length=200) 
    project = models.ForeignKey(Project, blank=True, null=True, verbose_name="Project") 
    notes = models.TextField("Notes", blank=True) 
    complete = models.BooleanField(default=False, verbose_name="Complete?") 
    status = models.IntegerField("Action Status", choices = STATUS, default=0) 

我需要返回查询的所有项目,其中有与状态没有动作< 2.

我想:

Project.objects.filter(action__status__gt = 1) 

但这返回所有的项目,因为在每个项目中,有一些行为与状态2与状态的一些行动小于2.另外,[R在结果查询中重复执行项目。我目前的解决方案是如下:

Project.objects.filter(action__status__gt =1).exclude(action__status__lt =2).annotate() 

这倒塌的重复结果,显示只有用实际行动大于1的动作状态但这是建立这样的查询的正确方法?如果我想要返回动作状态大于1的项目或没有动作的项目,该怎么办?

回答

0

我可能误解了您的要求,但我认为您可以使用注释做到这一点。

Project.objects.annotate(m = Min('action__status')).filter(Q(m = None) | Q(m__gt = 1))

生成的SQL是:

SELECT 
    "testapp_project"."id", "testapp_project"."name", 
    MIN("testapp_action"."status") AS "m" 
FROM "testapp_project" 
LEFT OUTER JOIN "testapp_action" ON ("testapp_project"."id" = "testapp_action"."project_id") 
GROUP BY "testapp_project"."id", "testapp_project"."name" 
HAVING(
     MIN("testapp_action"."status") IS NULL 
    OR MIN("testapp_action"."status") > 1 
) 

这是不言自明。

0

Django的ORM无法表达这一点。您将需要使用原始查询才能执行此操作。

+0

谢谢。我明白为什么这可能是真的。有关于如何构建这个原始查询的任何建议? –