2014-03-29 61 views
5

我想弄清楚如何使用select_relatedprefetch_related優化來自外鍵另一端的查詢。例如:Django在外鍵上正確使用select_related或prefetch_related

說我有一些車型如下列:

class Product(models.Model): 
    name = models.CharField(max_length=50) 

class ProductImage(models.Model): 
    image = models.ImageField(upload_to="images") 
    product = models.ForeignKey("myapp.Product", related_name="product_images") 

如果我想打印所有ProductImage的,我已經經歷了所有的產品進​​行迭代,然後,對每個產品,遍歷所有產品圖像。但是,這會產生O(n * m)個數據庫查詢。

for product in Product.objects.all(): 
    print product.product_images.all() 

我不知道是否有利用select_relatedprefetch_related這個查找減少到一個或兩個查詢的方式。

正如Django所記錄的,當我選擇ProductImage時,我可以得到select_related。如您所見,添加select_related會爲產品表創建JOIN。

>>> ProductImage.objects.all().query.sql_with_params() 
(u'SELECT "myapp_productimage"."id", ... FROM "myapp_productimage" .... 

>>> ProductImage.objects.select_related('product').query.sql_with_params() 
(u'SELECT "myapp_productimage"."id", ... FROM "myapp_productimage" LEFT OUTER JOIN .... 

但是,如何完成相反的操作?例如,如何查詢所有的Product,並讓它加入ProductImage?做類似下面的事情似乎並不奏效。

Product.objects.select_related('product_images').query.sql_with_params() 

在Django中是這樣的可能嗎?

感謝您的考慮。

回答

8

這正是prefetch_related所做的。

Product.objects.prefetch_related('product_images') 

然而,有一個在使用query.sql_with_params()診斷這是沒有意義的:prefetch_related確實查詢,而第二個將不會出現在那裏。您應該使用django.db.connection.queries來檢查Django正在進行的查詢,或者更好地使用Django調試工具欄來向您顯示。

+0

非常感謝Daniel。另外,很高興知道sql_with_params()沒有顯示完整的圖片。我會嘗試使用您建議的其他方法。 –

3

select_related在您有正向外鍵關係時使用,當存在反向外鍵關係時應該使用prefetch_related

相關問題