gpt4 book ai didi

python - 查询较少的父对象及其子对象列表

转载 作者:太空狗 更新时间:2023-10-30 01:02:54 26 4
gpt4 key购买 nike

我有一个要优化的 Django View 。它在页面上显示父对象及其子对象的列表。子模型将外键返回给父模型,因此 select_related 似乎不适用。

class Parent(models.Model):
name = models.CharField(max_length=31)

class Child(models.Model):
name = models.CharField(max_length=31)
parent = models.ForeignKey(Parent)

天真的实现使用 n+1 查询,其中 n 是父对象的数量,即。一个查询获取父列表,然后一个查询获取每个父列表的子列表。

我写了一个 View ,它在两个查询中完成这项工作 - 一个用于获取父对象,另一个用于获取相关的子对象,然后是一些 Python(我太尴尬了,无法在此处发布)来完成所有这些工作再次聚在一起。

一旦我发现自己导入了标准库的 collections 模块,我就意识到我可能做错了。可能有更简单的方法,但我缺乏找到它的 Django 经验。任何指针将不胜感激!

最佳答案

添加 related_name到外键,然后使用 prefetch_related添加到 Django 1.4 的方法:

Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.

This has a similar purpose to select_related, in that both are designed to stop the deluge of database queries that is caused by accessing related objects, but the strategy is quite different:

  • select_related works by creating a SQL join and including the fields of the related object in the SELECT statement. For this reason, select_related gets the related objects in the same database query. However, to avoid the much larger result set that would result from joining across a 'many' relationship, select_related is limited to single-valued relationships - foreign key and one-to-one.

  • prefetch_related, on the other hand, does a separate lookup for each relationship, and does the 'joining' in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related. It also supports prefetching of GenericRelation and GenericForeignKey.

class Parent(models.Model):
name = models.CharField(max_length=31)

class Child(models.Model):
name = models.CharField(max_length=31)
parent = models.ForeignKey(Parent, related_name='children')


>>> Parent.objects.all().prefetch_related('children')

所有相关的 child 都将在一个查询中获取,并使用使查询集具有相关的预填充缓存结果。然后在 self.children.all() 中使用这些 QuerySet电话。

Note 1 that, as always with QuerySets, any subsequent chained methods which imply a different database query will ignore previously cached results, and retrieve data using a fresh database query.

Note 2 that if you use iterator() to run the query, prefetch_related() calls will be ignored since these two optimizations do not make sense together.

关于python - 查询较少的父对象及其子对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12814066/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com