2011-10-19 22 views
9

tôi có các mô hình:Django đếm trên nhiều-nhiều

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) 

Tôi muốn có được một đếm bao nhiêu bài viết mỗi từ khóa. Về bản chất tôi muốn có một danh sách các từ khóa mà tôi có thể nhận được mỗi từ khóa để tính trọng số tương đối.

Tôi đã thử:

keyword_list=Article.objects.all().annotate(key_count=Count('keywords__keyword')) 

nhưng

keyword_list[0].key_count  

chỉ dường như để cho tôi số lượng từ khóa khác nhau mỗi bài viết có? Có bằng cách nào đó một tra cứu ngược lại không?

Mọi trợ giúp sẽ được đánh giá cao.

CẬP NHẬT

Vì vậy, tôi đã nhận nó làm việc:

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 } 

nhưng kết quả xem trong một số gớm ghiếc của các truy vấn. Tôi đã thử thực hiện các đề xuất đưa ra ở đây (cảm ơn) nhưng đây là chỉ có methid mà dường như làm việc tại thời điểm này. Tuy nhiên, tôi phải làm điều gì đó sai vì bây giờ tôi có hơn 400 truy vấn!

CẬP NHẬT

Wooh! Cuối cùng đã nhận nó làm việc:

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} 

Trả lời

16

Vì bạn muốn số điều mà có mỗi từ khóa, bạn phải làm điều đó theo cách khác:

>>> Keyword.objects.all().annotate(article_count=models.Count('article'))[0].article_count 
2 
+0

Tại sao điều này xuống bình chọn nó có vẻ như câu trả lời đúng, hoặc tôi thiếu một cái gì đó? – solartic

+2

Đây thực sự là câu trả lời đúng, nhưng có lẽ có thể sử dụng một chút giải thích. – jathanism

+0

Bạn có thể đơn giản hóa nó thành 'Keyword.objects.all(). Chú thích (Đếm ('bài viết')) [0] .article__count' – guival

1

tôi không biết làm thế nào bạn sẽ làm điều đó hiệu quả nhưng nếu bạn cần hoàn thành nó.

keywords = Keyword.objects.all() 
for keyword in keywords: 
    print 'Total Articles: %d' % (Article.objects.filter(keywords=keyword).count()) 
4

này cũng giống như câu trả lời từ Vebjorn Ljosa, nhưng với một bối cảnh nhỏ, nơi article_setrelated_name của đối tượng mối quan hệ ngược nhiều-nhiều.

keywords_with_article_counts = Keyword.objects.all().annotate(article_count=Count('article_set')) 

Để minh họa kết quả của bạn, nó sẽ dễ dàng hơn để trả lại .values():

keywords_with_article_counts.values('keyword', 'article_count') 

Trong đó sẽ trả về một danh sách các từ điển đó sẽ giống như thế này:

[{'article_count': 36, 'keyword': u'bacon'}, 
{'article_count': 4, 'keyword': u'unicorns'}, 
{'article_count': 8, 'keyword': u'python'}] 
+0

Cảm ơn. Điều đó làm cho nó rõ ràng hơn một chút, mặc dù tôi vẫn gặp sự cố khi tích hợp điều này vào quan điểm của tôi (xem câu hỏi đã chỉnh sửa của tôi). Nếu tôi trả lại một từ điển, thì quan điểm này sẽ khác biệt đáng kể, phải không? –

+0

Bạn có thể trả về 'keywords_with_article_counts' QuerySet như là để xem của bạn. Tôi chỉ cho thấy việc sử dụng phương thức '.values ​​()', cho phép bạn trả lại một từ điển của các trường mong muốn thay vì các cá thể mô hình. Đó chỉ là minh họa kết quả của 'article_count', xin lỗi nếu điều đó gây nhầm lẫn. – jathanism

+0

Bây giờ tôi có một phiên bản sửa đổi này làm việc trong vỏ của tôi, nhưng khi tôi đang cố gắng chuyển số lượng thành trọng lượng và phân phối từ khóa dưới dạng đối tượng, theo quan điểm của tôi ở trên, tôi ít bị mất. Bất kỳ lời khuyên về cách tôi tích hợp này? –

Các vấn đề liên quan