Django рассчитывает на многие-ко-многим

У меня есть модели:

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}
11
задан Darwin Tech 20 October 2011 в 16:15
поделиться