Django ORM将孩子的数量分组

鉴于以下models.py

class Parent(models.Model):
    name = models.CharField(max_length=100)

class Child(models.Model):
    parent = models.ForeignKey('Parent', related_name='children')
    status = models.CharField(max_length=10, choices=(('ok', 'ok'), ('fail', 'fail')))

我想访问父级模型/视图到父级孩子的分组计数。

例如

parent.num_ok, parent.num_failed

要么

 parent.child_counts_per_status['ok']

计数需要在SQL中完成,因为为所有父母加载所有孩子,然后在内存中计数它们的开销太大(可能每个父母有数以万计的孩子)

如果我要在ORM之外写这个,我会做类似如下的事情:

select parent.id, parent.name, child.status, count(*) from parent
inner join child on child.parent_id = parent.id
group by parent.id, parent.name, child.status

不过,看到我将限制父母的数量(通过分页),可能会有以下几点:

select parent.* from parent where ... (page is)

然后每个父项的一个执行:

select status, count(*) from child where parent_id = :parent_id
group by status

这些选项是否可以通过Django ORM获得?

另外如果是这样的话......我如何将它插入到对象模型中? 我使用的是Django Rest Framework,我猜这个查询会进入views.py目前的样子:

class ParentViewSet(viewsets.ModelViewSet):

    queryset = Parent.objects.all()

以下将按照您的建议,使用名为num_oknum_fail的属性中的两种子类型的计数为每个父对象注释。

这在内部创建的SQL几乎与您建议的SQL几乎相同,这使得将数值计入数据库,而不是在Python或Django中完成。

from django.db.models import Count, Case, When, IntegerField

...

queryset = Parent.objects.annotate(
               num_ok=Count(Case(
                            When(children__status='ok', then=1),
                                output_field=IntegerField()))
           ).annotate(
               num_fail=Count(Case(
                              When(children__status='fail', then=1),
                                output_field=IntegerField())))

这将允许遍历父对象并检索计数,如下所示:

for parent in queryset:
    print(parent.num_ok)
    print(parent.num_fail)

如果你想为特定的父母(比如parent1)计数'ok'的孩子,请使用

parent1.children.filter(status='ok').count()

如果您需要为所有父母计数好的孩子,那么您可以使用注释,例如为每个父母打印孩子计数,您将使用

from django.db.models import Count 

parents = Parent.objects.filter(children__status='ok').annotate(c_count=Count('children'))

for p in parents:
  print p.c_count

分别为您将使用的queryset

Parent.objects.filter(children__status='ok').distinct()

(我们使用不同来消除重复)

链接地址: http://www.djcxy.com/p/60213.html

上一篇: Django ORM grouped count of children

下一篇: Django object composition with OneToOneField