[英]Django count unique items in field and group by parent field with field selection
[英]Django Count of Items in a Field
models.py
class Event(models.Model):
name = models.CharField(max_length=20, unique=True)
distance = models.IntegerField()
date = models.DateField()
class Category(models.Model):
name = models.CharField(max_length=20, unique=True)
description = models.CharField(max_length=20, unique=True)
isnew = models.BooleanField(default=False)
class Result(models.Model):
event = models.ForeignKey(Event)
category = models.ForeignKey(Category)
score = models.IntegerField()
我想进行查询以返回给定事件的Result表中每个唯一Category的计数。
我现在正在做的是:
results = Result.objects.filter(event=myevent)
categorycountdict = {}
for r in results:
if r.category in categorycountdict:
categorycountdict[r.category] += 1
else:
categorycountdict[r.category] = 1
有没有更好的方法,可能是通过查询而不是python。
您可以将annotate()
与values()
。 这种方法显示在values()
的文档中。 要获取每个类别名称的计数,您可以执行以下操作:
from django.db.models import Count
categories = Result.objects.filter(
event=myevent,
).order_by('category').values(
'category__name'
).annotate(count=Count('category__name'))
这将返回一个字典列表,其中包含键category__name
和count
,例如:
[{'count': 3, 'category__name': u'category1'}, {'count': 1, 'category__name': u'category2'}]
您可以使用字典理解将其转换为单个字典:
counts_by_category = {d['category__name']: d['count'] for f in categories}
使用annotate
:
from django.db.models import Count
Results.objects.filter(event=some_event).annotate(Count('category'), distinct=True)
python标准库中有collections.Counter :
results = Result.objects.filter(event=myevent).select_related('category')
c = Counter(r.category for r in results)
现在c是一个类似dict的对象,其中键是Category实例,值是计数。
但是,此选项不适用于大型数据集,因为它不使用数据库功能。 因此,如果您有大量数据,那么使用值,注释和计数的方法更合适。
这里使用select_related以消除每个结果的数据库命中。 基本上,它使用join进行1次查询,并为类别生成python对象。
事实证明,ManyToManyField仅跟踪唯一记录,因此下面的答案是不正确的。
您的事件和类别模型通过结果模型公开多对多连接。
您可以在Django中使用through来表达它(注意类别ManyToManyField):
class Event(models.Model):
name = models.CharField(max_length=20, unique=True)
distance = models.IntegerField()
date = models.DateField()
categories = models.ManyToManyField(Category, through='Result', related_name='events')
在您的代码中,对于给定的事件,您可以像这样查询:
event.categories.count()
考虑到Alasdair的注意事项:
event.categories.values('pk').annotate(count=Count('pk'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.