2014-04-22 15 views
9

Bunun gibi bir durum var (gerçek kod bir şablona bağlanır ve kısalık için atlanır).Django'nun yalnızca sayım için önceden getirilmiş_sayısı

threads = Thread.objects.all() 
for thread in threads: 
    print(thread.comments.count()) 
    print(thread.upvotes.count()) 

Ben oldukça Django'nın müthiş prefetch_related yöntemi kullanılarak sorgularının toplam sayısını azaltmak için idare ettik.

threads = Thread.objects.prefetch_related('comments').prefetch_related('upvotes') 

Ancak, bu durumun daha da optimize edilip edilemeyeceğini merak ediyorum. Anladığım kadarıyla prefetch_related, ilgili modellerle ilişkili tüm verileri alır. Modellerin kendileriyle ilgili değil, sadece ilgili modellerin miktarını önemsediğimi düşünürsek, bu sorgu, daha fazla optimize edilebileceği gibi gereksiz veri elde etmeyecek gibi görünüyor. Django'da bunu ham SQL'e düşürmeden yapmanın bir yolu var mı? Haklısın

cevap

11

, bunu yapmak istediğin sayısı elde ise veritabanından tüm bu veri getirmesi savurgan.

threads = (Thread.objects.annotate(Count('comments', distinct=True)) 
         .annotate(Count('upvotes', distinct=True))) 
for thread in threads: 
    print(thread.comments__count) 
    print(thread.upvotes__count) 

fazla bilgi için annotation documentation bakınız: Ben ek açıklama düşündürmektedir.

+0

İstediğim şey bu kadar harika, teşekkürler! Ayrıca, Django'nun dokümanlarını incelemek 1.7 gibi görünüyor, yeni Prefetch sınıfını ve kullanılmayan alanları yok eden özel bir sorgu seti kullanarak anlattığım şeye benzer bir şey elde edebilecektir. Ancak çözümünüz, Django'nun kanamayan sürümleriyle çalışır. – rectangletangle

+3

@rectangletangle: İlgilendiğiniz tek şey sayı ise, ek açıklama hala "prefetch_related" den daha iyi çalışmalıdır. Her şeyi idrak etmekten vazgeçseniz bile, her iş parçacığı için bir tam sayı (sayı) alabildiğinizde her yorum için bir tamsayı almak için bir neden yoktur. –

+0

Bu iyi bir nokta. Bu ve uyumluluk arasında, ben bu kullanım davası için üstün bir çözüm var düşünüyorum. – rectangletangle