2010-12-20 23 views
1

我有兩個模型的所有對象:獲取與空集相關的那些

class Content(models.Model): 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField(db_index=True) 
    content_object = generic.GenericForeignKey() 
    show = models.BooleanField(default=False) 

class Foo(models.Model): 
    rel = generic.GenericRelation(Content) 

,我想所有的Foo方法這是相關內容的對象(將只有一個)有show==True,或者沒有按根本沒有相關的對象。就像:

Foo.objects.filter(Q(rel__show=True) | Q(rel__hasnone=True)) 

但當然在django中沒有什麼像hasnone

是否有任何其他方式可以完成該操作(不幸的是,聚合不適用於泛型關係,而且我無法計數項目)。

+0

我在下面看到了你的答案,但這裏有一個更簡單的想法:循環遍歷相關集合並將具有相關記錄的所有對象附加到列表中。然後,再次遍歷模型,並跳過列表中的所有記錄。 這會慢一些,但有利於完全使用python和Django ORM。 – 2014-11-08 16:37:46

回答

1

好的,我想我的答案可以滿足我們中的一些人(不幸的是不是我)。

我需要什麼LEFT OUTER JOIN這Django不支持(所有聯接由用戶聲明是INNER的),這樣的:

SELECT *, `foobar_bar`.`show` AS `show` FROM `foobar_foo` LEFT OUTER JOIN `foobar_bar` 
    ON (`foobar_foo`.`id` = `foobar_bar`.`object_id` and 
     ctype = `foobar_bar`.`content_type_id`) 
    WHERE show=TRUE OR show=NULL 

我認爲兩款車型都在foobar應用和CTYPE是content_type的型號爲Foo。我還沒有找到辦法做這樣的查詢,但我們可以這樣做:

SELECT *, `foobar_bar`.`show` AS `show` FROM `foobar_foo` LEFT OUTER JOIN `foobar_bar` 
    ON (`foobar_foo`.`id` = `foobar_bar`.`object_id` 
    WHERE (show=TRUE OR show=NULL) AND ctype = `foobar_bar`.`content_type_id` 

這不是令人滿意的排他性(可以加入不同的CTYPE只是立足於對象的ID元組),但仍然是有用的。我在link text找到了這樣的查詢方法。這將是這樣的:

qs = Foo.objects.all() 

qs.query.join((None, 'foobar_foo', None, None)) 
qs.query.join(('foobar_foo', 'foobar_bar', 'id', 'object_id'), promote=True) 
foos. 
qs = qs.extra(select = {'show': 'foobar_bar.show',}, 
       where = "(show=TRUE OR show=NULL) AND ctype = `foobar_bar`.`content_type_id`") 

一般使用query.join((,), promote=True)會讓我們LEFT JOIN QUERY,而不是INNER,但我們只有一個可以傳遞參數,它是太少完全解決這個問題,但還是有用的。

相關問題