获取所有对象与空集相关的对象

时间:2010-12-20 23:12:41

标签: django django-models django-queryset

我有两个型号:

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

有没有其他方法可以实现这一点(遗憾的是,聚合不适用于通用关系,我无法计算项目。)

1 个答案:

答案 0 :(得分:1)

好的,我想我已经回答了可以满足我们中的一些人(不幸的是不是我)。

我需要的是Django不支持的LEFT OUTER JOIN(用户声明的所有连接都是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是模型Foo的content_type。我还没有办法做这样的查询,但我们可以这样做:

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`

它不是唯一的排他性(可以基于对象的id加入具有不同ctype的元组)但仍然有用。我在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 QUERY JOIN而不是INNER,但我们只能传递一个ON参数,这个参数太少而不能完全解决该问题但仍然有用。