Django外键字段产生大量查询

5

我一直在编写内部网站,同时一整天都在沉迷于Django,但现在我注意到模型中的ForeignKeys非常低效。

我的模型有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还比较新,希望我只是在做一些愚蠢的事情。这绝对是一个非常棒的框架。

1个回答

5
你应该使用 select_related 函数,例如:
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

等等。如果您使用了selected related,则会在幕后执行联接操作,并自动跟踪和加载所有这些外键,以便在第一个查询中仅执行一个数据库查询。因此,在上面的示例中,你将得到:

# 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

谢谢!有这个函数确实很有意义。现在运行了9个查询。由于表很小,我不介意它加载所有数据(显然这样更好)。 - Dan Breen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接