2009-07-10 83 views
5

我一整天都在Django上流口水,而在創紀錄的時間內編寫一個內部網站,但現在我注意到模型中的ForeignKeys效率非常低。很多來自django foreignkey fields的查詢

我有一個有6個ForeignKeys的模型,它們基本上是查找表。當我查詢所有對象並將它們顯示在模板中時,它每個項目運行約10個查詢。這裏有一些代碼,應該更好地解釋它:

class Website(models.Model): 
    domain_name = models.CharField(max_length=100) 
    registrant = models.ForeignKey('Registrant') 
    account = models.ForeignKey('Account') 
    registrar = models.ForeignKey('Registrar') 
    server = models.ForeignKey('Server', related_name='server') 
    host = models.ForeignKey('Host') 
    target_server = models.ForeignKey('Server', related_name='target') 

class Registrant(models.Model): 
    name = models.CharField(max_length=100) 

...和5個更簡單的表。有155個網站記錄,並且在我使用的視圖中:

Website.objects.all() 

它最終執行1544個查詢。在模板中,我使用所有的外交領域,如:

<span class="value">Registrant:</span> <a href="/filter/registrant/{{ website.registrant.id }}">{{ website.registrant.name }}</a><br /> 

所以我知道它會運行很多查詢的...但它看起來這是過度的。這是正常的嗎?我不應該這樣做嗎?

我對Django很新,所以希望我只是在做一些愚蠢的事情。這絕對是一個非常驚人的框架。

回答

5

您應該使用select_related function,例如,

Website.objects.select_related() 

這樣它會自動完成時進行查詢,而不是裝載他們的需求爲他們所使用的連接,並遵守所有的外鍵。 Django懶洋洋地從數據庫加載數據,因此默認情況下會得到以下行爲

# one database query 
website = Website.objects.get(id=123) 

# first time account is referenced, so another query 
print website.account.username 

# account has already been loaded, so no new query 
print website.account.email_address 

# first time registrar is referenced, so another query 
print website.registrar.name 

等等。如果使用選定的相關,則在幕後執行聯接,並且所有這些外鍵都會自動跟隨並加載到第一個查詢上,因此只執行一個數據庫查詢。所以在上面的例子中,你會得到

# one database query with a join and all foreign keys followed 
website = Website.objects.select_related().get(id=123) 

# no additional query is needed because the data is already loaded 
print website.account.username 
print website.account.email_address 
print website.registrar.name 
+0

謝謝!這個功能絕對有意義。現在它運行了9個查詢。由於表格很小,我不在乎它是加載所有的數據(顯然它更好)。 – 2009-07-10 20:34:26