使用Django ORM,如何在Many关系中过滤同一记录的两个字段?

时间:2014-06-17 20:09:11

标签: django postgresql django-orm

我有一个像这样的数据库架构:

class Family(models.Model):
    pass

class Child(models.Model):
    family = models.ForeignKey(Family)

    name   = models.TextField()
    age    = models.IntegerField()
    gender = models.CharField(max_length=1)

我想要一个查询,返回有5岁以下男孩的家庭中的所有孩子。

我该如何表达?我得到的最近的是:

# WRONG: this is no good, it will only return boys under 5, but I want all
# children in families with boys under 5.
Child.objects.filter(gender='M', age__lt=5)

# WRONG: this is no good, it is closer but will also return children in 
# families with a 6yo boy and a 3yo girl.
Child.objects.filter(family__child__gender='M', family__child__age__lt=5)

4 个答案:

答案 0 :(得分:1)

你说你想要所有男孩在5岁以下男孩的家庭 这是一个很大的暧昧,但我会假设你想要的家庭至少包含一个不到5岁的男孩

这样可行:

families = Family.objects.filter(child__gender='M', child__age__lt=5).prefetch_related('child')

然后你可以迭代家庭对象来检索他们各自的孩子

答案 1 :(得分:1)

获取有5岁以下男孩的id的{​​{1}},然后在这些Family上过滤Child。以下查询仅对数据库命中一次:

id

答案 2 :(得分:1)

您可以尝试__in - 这样的查询:

boys_under_5 = Child.objects.filter(gender='M', age__lg=5)
Child.objects.filter(family__child__in=boys_unter_5)

至于为什么你的原始查询不起作用,我建议阅读generared SQL:

print Child.objects.filter(family__child__gender='M', family__child__age__lt=5).query

答案 3 :(得分:0)

正如@knbk在评论中指出的那样,当我写这个问题时,我确实错了。我假设一个不存在的默认行为。那么,最好的答案是我给出的答案:

Child.objects.filter(family__child__gender='M', family__child__age__lt=5)

如果你想要找回有一个男孩和一个(可能是不同的)5岁以下孩子的家庭中的所有孩子,你必须这样做:

Child.objects.filter(family__child__gender='M').filter(family__child__age__lt=5)

这里提供的文档链接@knbk详细介绍了该功能:https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

如果他回答,我会将积分转移给他。