tengo los modelos:Django contar con muchos-a-muchos
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)
quiero obtener un recuento de cómo muchos artículos tienen cada palabra clave. En esencia, quiero tener una lista de palabras clave donde pueda obtener el recuento de cada uno para darle una ponderación relativa.
que he intentado:
keyword_list=Article.objects.all().annotate(key_count=Count('keywords__keyword'))
pero
keyword_list[0].key_count
sólo parece que me diera el número de diferentes palabras clave cada artículo tiene? ¿Es de alguna manera una búsqueda inversa?
Cualquier ayuda sería muy apreciada.
ACTUALIZACIÓN
Así que tengo trabajo:
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 }
pero la vista los resultados en una serie espantosa de consultas. He tratado de implementar las sugerencias dadas aquí (gracias) pero este es el único metid que parece funcionar en este momento. Sin embargo, debo estar haciendo algo mal ya que ahora tengo más de 400 consultas.
ACTUALIZACIÓN
Wooh! Finalmente lo consiguió trabajo:
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}
¿Por qué es esta votación negativa parece ser la respuesta correcta, ¿o me falta algo? – solartic
Esta es de hecho la respuesta correcta, pero probablemente podría usar una pequeña explicación. – jathanism
Puede simplificarlo a 'Keyword.objects.all(). Annotate (Count ('artículo')) [0] .article__count' – guival