2014-04-22 52 views
9

我有這樣的情況(實際代碼綁定在模板中,爲簡潔起見省略)。Django的prefetch_related僅支持計數

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

我設法大大減少了使用Django的真棒prefetch_related方法的查詢總數。

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

但是,我想知道這種情況是否可以進一步優化。據我所知,prefetch_related檢索所有與相關模型相關的數據。由於我只關心相關模型的數量,而不關心模型本身,因此似乎可以進一步優化此查詢,以便它不檢索大量不必要的數據。有沒有辦法在Django中做到這一點,而不會下降到原始SQL?

回答

11

你是對的,如果你想要做的就是獲取數據,從數據庫中獲取所有數據是浪費的。我建議註釋:

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) 

查看annotation documentation瞭解更多信息。

+0

太棒了,這正是我想要的,謝謝!同樣通過Django的文檔搜索,它看起來像1.7將能夠實現類似於我所描述的使用新的Prefetch類和延遲未使用的字段的自定義查詢集。但是,您的解決方案適用於Django的非流行版本。 – rectangletangle

+3

@rectangletangle:如果你關心的只是計數,註釋仍然應該比'prefetch_related'更好。即使你推遲了除id之外的所有內容,當你可以爲每個線程獲取一個整數(count)時,沒有理由爲每個註釋獲取一個整數。 –

+0

這是一個好點。在這個和兼容性之間,我認爲你有這個用例的優秀解決方案。 – rectangletangle