2012-10-20 104 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

謝謝。我明白爲什麼這可能是真的。有關於如何構建這個原始查詢的任何建議? –