使用模型关系防止多个SQL查询

时间:2013-10-11 13:15:19

标签: django

当我使用django ORM时,是否可以防止多个查询?例如:

product = Product.objects.get(name="Banana")
for provider in product.providers.all():
    print provider.name

此代码将生成2个SQL查询:

  

1 - SELECT•••FROM stock_product WHERE stock_product.name ='Banana'

     

2 - SELECT stock_provider.id,stock_provider.name FROM stock_provider INNER JOIN stock_product_reference ON(stock_provider.id = stock_product_reference.provider_id)WHERE stock_product_reference.product_id = 1

我承认,我对某些项目使用Doctrine(PHP)。使用原则,可以在检索对象时指定连接(关系填充在对象中,因此无需再次查询数据库以获取属性关系值)。

是否可以对Django的ORM做同样的事情?

PS:我的问题是全面的,英语不是我的主要语言。

2 个答案:

答案 0 :(得分:1)

您可以使用prefetch_related(有时与select_related结合使用)在一个查询中获取所有相关对象:https://docs.djangoproject.com/en/1.5/ref/models/querysets/#prefetch-related

答案 1 :(得分:1)

在Django 1.4或更高版本中,您可以使用prefetch_related。它就像select_related但允许M2M关系等。

product = Product.objects.prefetch_related('providers').get(name="Banana")

但是仍然会收到两个查询。来自文档:

  另一方面,

prefetch_related对每个关系进行单独查找,并在Python中进行“加入”。

至于将其打包成单个查询,Django不会像Doctrine那样做,因为它没有对结果集进行那么多的后处理(Django必须删除所有冗余列数据,因为你每个提供商会得到一行,每个行都会有product个字段的副本。)

因此,如果你想把它打包到一个查询,你将不得不扭转它并在Provider表上运行查询(我猜你的模式):

providers = Provider.objects.filter(product__name="Banana").select_related('product')

这应该将其打包为一个查询,您不会从中获取单个product ORM对象,而是需要通过{{1}获取产品字段}。