使用 select_related 从两个模型中获取值

Posted

技术标签:

【中文标题】使用 select_related 从两个模型中获取值【英文标题】:Using select_related to get values two models away 【发布时间】:2015-04-06 09:15:09 【问题描述】:

假设我有以下内容:

class Model1(Model):

    field1 = ForeignKey(Model2)
    query_field = IntegerField()

class Model2(Model):
    field2 = ForeignKey(Model3)

class Model3(Model)
    field3 = SomeDesiredValue

现在我想查询Model1 表并从Model3 中提取field3。我的问题是关于select_related 的性能。

如果我这样做

query = Model1.objects.filter(query_field=filter_paramter).select_related('field1')

我假设以下内容仍会访问数据库?

query[0].field1.field2.field3

我可以执行以下操作以使其更快吗?

query = Model1.objects.filter(query_field=filter_paramter).select_related('field1__field2')

【问题讨论】:

FWIW,您可以通过说print query.query(使用示例中的变量)来查看实际执行的 SQL 查询——here 是一个相关问题。 【参考方案1】:
class Model1(Model):

    field1 = ForeignKey(Model2, related_name="model2")
    query_field = IntegerField()

class Model2(Model):
    field2 = ForeignKey(Model3, related_name="model3")

class Model3(Model)
    field3 = SomeDesiredValue

做这样的事情会更好。

mdls1 = Model1.objects.filter(query_field=filter_paramter).first()

related_model3s = mdls1.field1.model3.all()

这将从Model2获取所有field2(这意味着所有与Model2相关的Model3) 如果您需要任何帮助,请询问:)

【讨论】:

【参考方案2】:

是的,第一个查询导致两个数据库命中,第二个查询将使用一个带有两个 INNER JOINS 的 SQL 查询来处理:

SELECT "app_model1"."id", "app_model1"."field1_id",
       "app_model1"."query_field", "app_model2"."id",
       "app_model2"."field2_id", "app_model3"."id",
       "app_model3"."field3"
FROM "app_model1"
INNER JOIN "app_model2" ON ( "app_model1"."field1_id" = "app_model2"."id" )
INNER JOIN "app_model3" ON ( "app_model2"."field2_id" = "app_model3"."id" )
WHERE "app_model1"."query_field" = 1 LIMIT 1

【讨论】:

感谢您的回答。快速澄清一下,当我使用.select_related('field1__field2') 时,它会从Model2 中提取所有内容吗?或者只是与Model3 表进行连接需要什么? 它为Model2Model3 模型加载所有内容。所以obj = query.first() \n obj.field1.some_attr \n obj.field1.field2.other_attr \n obj.field1.field2.field3 - 这一切都将通过一个 SQL 查询来处理。

以上是关于使用 select_related 从两个模型中获取值的主要内容,如果未能解决你的问题,请参考以下文章

使用 select_related 时,如何使用相关模型的自定义管理器?

select_related 与反向外键

如何使用 select_related 获取 ManyToMany 字段值

如何强制 Django Admin 使用 select_related?

Django 管理员内联:select_related

django select_related - 何时使用它