2009-07-10 84 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