【问题标题】:In Django, how do I query that all of the related objects have the same value for a certain field?在 Django 中,如何查询所有相关对象对于某个字段具有相同的值?
【发布时间】:2019-09-19 20:52:21
【问题描述】:

假设我在 Django 中有以下模型:

    class Parent(models.Model):
        pass

    class Child(models.Model):
        parent = models.ForeignKey(Parent, related_name='children', null=True)
        foo = models.CharField(max_length=5, blank=True, null=True)

如何查询Parent 模型以查找所有Parent 记录,其中所有childrenfoo 的值为“ABC”?

如果我运行: Parent.objects.filter(children__foo='ABC'),它返回Parent 对象,其中至少一个childrenfoo 的值为'ABC',这不是我想要的。任何帮助表示赞赏,谢谢。

【问题讨论】:

    标签: sql django django-models


    【解决方案1】:

    你可以相反的工作:我们首先过滤相关的Children,这样我们只有foo不是'ABC'的孩子,然后我们计算数量的Children。如果为零,我们知道所有这些孩子都有'ABC'(这包括没有孩子的Parents)。

    from django.db.models import Count, Q
    
    Parent.objects.annotate(
        nabc=Count('children', filter=~Q(children__foo='ABC'))
    ).filter(
        nabc=0
    )

    这将产生一个如下所示的查询:

    SELECT parent.*,
           COUNT(CASE WHEN NOT (child.foo = ABC AND child.foo IS NOT NULL)
                 THEN child.id ELSE NULL END) AS nabc
    FROM parent LEFT OUTER JOIN child ON parent.id = child.parent_id
    GROUP BY parent.id
    HAVING COUNT(CASE WHEN NOT (child.foo = ABC AND child.foo IS NOT NULL)
                 THEN child.id ELSE NULL END) = 0
    

    【讨论】:

    • 谢谢!这做到了。我通过运行 2 个查询找到了解决方案,但我更喜欢这个。这是我想出的:children = Child.objects.exclude(foo='ABC').order_by('parent_id').distinct().values_list('parent_id', flat=True) Parent.filter(~Q(id__in=list(children)))
    猜你喜欢
    • 2020-05-25
    • 2011-06-11
    • 2020-06-16
    • 2021-04-01
    • 2017-10-29
    • 2020-06-08
    • 1970-01-01
    • 2016-05-27
    • 2015-10-17
    相关资源
    最近更新 更多