我有两个型号:
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 :(得分: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参数,这个参数太少而不能完全解决该问题但仍然有用。