我有模特:
class Article(models.Model):
title = models.TextField(blank=True)
keywords = models.ManyToManyField(Keyword, null=True, blank=True)
class Keyword(models.Model):
keyword = models.CharField(max_length=355, blank=True)
我想知道每个关键字有多少篇文章。从本质上讲,我希望有一个关键字列表,我可以将每个关键字计算为相对权重。
我试过了:
keyword_list=Article.objects.all().annotate(key_count=Count('keywords__keyword'))
但是
keyword_list[0].key_count
似乎只给了我每篇文章中不同关键字的数量?它是以某种方式反向查找吗?
非常感谢任何帮助。
更新
所以我得到了它的工作:
def keyword_list(request):
MAX_WEIGHT = 5
keywords = Keyword.objects.order_by('keyword')
for keyword in keywords:
keyword.count = Article.objects.filter(keywords=keyword).count()
min_count = max_count = keywords[0].count
for keyword in keywords:
if keyword.count < min_count:
min_count = keyword.count
if max_count > keyword.count:
max_count = keyword.count
range = float(max_count - min_count)
if range == 0.0:
range = 1.0
for keyword in keywords:
keyword.weight = (
MAX_WEIGHT * (keyword.count - min_count) / range
)
return { 'keywords': keywords }
但该视图会导致大量查询。我已经尝试过实施这里给出的建议(谢谢),但这是目前唯一可行的方法。但是,我必须做错事,因为我现在有400多个查询!
更新
呜!终于搞定了:
def keyword_list(request):
MAX_WEIGHT = 5
keywords_with_article_counts = Keyword.objects.all().annotate(count=Count('keyword_set'))
# get keywords and count limit to top 20 by count
keywords = keywords_with_article_counts.values('keyword', 'count').order_by('-count')[:20]
min_count = max_count = keywords[0]['count']
for keyword in keywords:
if keyword['count'] < min_count:
min_count = keyword['count']
if max_count < keyword['count']:
max_count = keyword['count']
range = float(max_count - min_count)
if range == 0.0:
range = 1.0
for keyword in keywords:
keyword['weight'] = int(
MAX_WEIGHT * (keyword['count'] - min_count) / range
)
return { 'keywords': keywords}
答案 0 :(得分:17)
由于您需要包含每个关键字的文章数量,因此您必须采用另一种方式:
>>> Keyword.objects.all().annotate(article_count=models.Count('article'))[0].article_count
2
答案 1 :(得分:4)
这与Vebjorn Ljosa的答案相同,但有一点上下文,其中article_set
是反向多对多关系对象的related_name
。
keywords_with_article_counts = Keyword.objects.all().annotate(article_count=Count('article_set'))
为了说明您的结果,返回.values()
:
keywords_with_article_counts.values('keyword', 'article_count')
这会返回一个类似于下面的词典列表:
[{'article_count': 36, 'keyword': u'bacon'},
{'article_count': 4, 'keyword': u'unicorns'},
{'article_count': 8, 'keyword': u'python'}]
答案 2 :(得分:1)
我不知道你如何有效地做到这一点,但如果你需要完成它。
keywords = Keyword.objects.all()
for keyword in keywords:
print 'Total Articles: %d' % (Article.objects.filter(keywords=keyword).count())