0

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

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

此代码将进行 2 个 SQL 查询:

1 - 选择 ••• 从 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:我希望我的问题很全面,英语不是我的主要语言。

4

2 回答 2

1

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

于 2013-10-11T13:25:41.490 回答
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')

这应该将其打包为一个查询,您不会从中获得单个productORM 对象,而是需要通过providers[k].product.

于 2013-10-11T13:31:13.533 回答