繁体   English   中英

Django字段中的项目计数

[英]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__namecount ,例如:

[{'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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM