来自django foreignkey字段的大量查询

Dan*_*een 5 django

在创纪录的时间内编写内部网站时,我整天都在为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)
Run Code Online (Sandbox Code Playgroud)

......还有5个简单的表格.有155个网站记录,在我正在使用的视图中:

Website.objects.all()
Run Code Online (Sandbox Code Playgroud)

它最终执行1544个查询.在模板中,我使用了所有外来字段,如:

<span class="value">Registrant:</span> <a href="/filter/registrant/{{ website.registrant.id }}">{{ website.registrant.name }}</a><br />
Run Code Online (Sandbox Code Playgroud)

所以我知道它会运行很多查询...但似乎这是过分的.这是正常的吗?我不应该这样做吗?

我对Django很新,所以希望我只是做一些愚蠢的事情.这绝对是一个非常棒的框架.

Eli*_*ght 5

您应该使用select_related函数,例如

Website.objects.select_related()
Run Code Online (Sandbox Code Playgroud)

这样它将自动执行连接并在执行查询时跟踪所有这些外键,而不是在使用它们时根据需要加载它们.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
Run Code Online (Sandbox Code Playgroud)

等等.如果使用选定的相关,则在后台执行连接,并在第一个查询中自动跟踪和加载所有这些外键,因此只执行一个数据库查询.所以在上面的例子中,你会得到

# 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
Run Code Online (Sandbox Code Playgroud)