Python Django ORM儿童分组计数
给定以下模型.pyPython Django ORM儿童分组计数,python,django,orm,Python,Django,Orm,给定以下模型.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
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')))
我想在父模型/视图上访问父模型/视图的子对象的分组计数
e、 g
或
计数需要在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()
如果您想获得特定父级(如parent1)的“ok”子级计数,请使用
parent1.children.filter(status='ok').count()
如果您需要计算所有家长的“ok”子女数,那么您可以使用,例如,要打印每个家长的子女数,您将使用
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
Parent.objects.filter(children__status='ok').distinct()
分别用于您将使用的queryset
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
Parent.objects.filter(children__status='ok').distinct()
我们使用消除重复如果您想获得特定父级(如parent1)的“ok”子级计数,请使用
parent1.children.filter(status='ok').count()
如果您需要计算所有家长的“ok”子女数,那么您可以使用,例如,要打印每个家长的子女数,您将使用
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
Parent.objects.filter(children__status='ok').distinct()
分别用于您将使用的queryset
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
Parent.objects.filter(children__status='ok').distinct()
我们使用以消除重复以下内容将按照您的建议,在名为num_ok和num_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)
下面将按照您的建议,使用名为num_ok和num_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)
谢谢接受了另一个答案,因为在现实生活中,如何处理同一数据库调用中的多个雕像更为清晰。我不止有两个,但这有助于我的总体理解。谢谢。我接受了另一个答案,因为在现实生活中,如何处理同一数据库调用中的多个雕像更为清晰,我不止有两个,但这有助于我的总体理解。