当我使用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:我的问题是全面的,英语不是我的主要语言。
答案 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}获取产品字段}。