【问题标题】:Filter queryset using child object fields使用子对象字段过滤查询集
【发布时间】:2021-06-17 05:47:42
【问题描述】:

我有两个模型 Parent 和 Child

class Parent(models.Model):
    id = models.IntegerField(...)

class Child(models.Model)
    id = models.IntegerField(...)
    parent = models.ForeignKey(Parent, ...)
    wanted = models.CharField(default="yes")

我想过滤所有与该父级一起出现的子级将“想要”为“是”的所有父级对象

我的代码:

    def containsYes(self):
        yes_ids = []
        qs = self.get_queryset()
        for q in qs:
            children = Child.objects.filter(parent_id = q.id)
            count = children .count()
            if children.filter(wanted = 'yes').count() == count
            yes_ids.append(q.id)
        return qs.filter(id__contains = yes_ids)

我知道这段代码效率很低,并且想要一个只使用查询的更好的解决方案

PS:我是 django 新手

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    我们可以排除存在不想要的孩子的Parents,以便我们可以使用:

    from django.db.models import F, Count, Q
    
    Parent.objects.annotate(
        nchild=Count('child')
        nchild_wanted=Count('child', filter=Q(child__wanted=True))
    ).filter(
        nchild=F('nchild_wanted')
    )

    因此我们首先计算相关Childs 的数量,并且将wanted 相关Childs 的数量设置为True。然后我们过滤,只保留这两个注解相同的Parent对象。

    由于,可以利用.alias(…) [Django-doc] 来防止SELECT 子句和HAVING 子句中的计数:

    from django.db.models import F, Count, Q
    
    Parent.objects.alias(
        nchild=Count('child')
        nchild_wanted=Count('child', filter=Q(child__wanted=True))
    ).filter(
        nchild=F('nchild_wanted')
    )

    【讨论】:

      【解决方案2】:
      1. 在子模型中给父相关名称:

      parent = models.ForeignKey(Parent, ..., related_name=“children”)

      1. 将 Wanted 字段更改为布尔值并将其默认为 True,您可以执行以下操作:

      Parent.objects.filter(children__wanted=True).exclude(children__wanted =False)

      或者您可以调用 Parent.objects.exclude(children__wanted=False) 以防此布尔值不可为空。

      【讨论】:

      • 这将返回所有存在需要的孩子的Parents,而不是所有孩子。因此,查询集将检索一个有两个孩子的Parent,一个想要,另一个不想要。
      猜你喜欢
      • 2015-10-28
      • 2011-12-24
      • 1970-01-01
      • 2023-01-16
      • 2018-09-28
      • 2020-06-16
      • 1970-01-01
      • 2012-04-19
      • 2022-12-14
      相关资源
      最近更新 更多