是否可以在 Wagtail 页面中使用 prefetch_related 检索相关的(父页面、子页面)?
Is using prefetch_related to retrieve related (parents, children pages) possible In Wagtail Pages?
我面临的问题是重复的查询数量,这使得在页面模型上使用 get_parent() 或 get_children() 时应用程序变慢。如果父页面有模板中使用的图像文件,它也会增加。
所以我正在寻找一种方法来 prefetch_related 页面而不建立外键关系。
假设我有一个 TvSeries 页面模型和一个剧集页面模型:
class TvSeries(Page):
name = models.CharField()
producer = models.CharField()
subpage_types = ['Episode']
class Episode(Page):
title = models.CharField()
number = models.CharField()
parent_page_types = ['TvSeries']
查询剧集模型需要预取TvSeries!如何减少数据库调用?是否可以使用预取和 select 相关?如果是的话怎么办?如果没有,查询数量增加的解决方案是什么?
prefetch_related
不能用于 parent/child 页面关系,因为它们不使用标准的 Django ForeignKey
关系——相反,Wagtail(和 Treebeard)使用 path
字段来表示树的位置。这使得执行无法使用 ForeignKey
高效完成的查询成为可能,例如获取页面的所有后代(在任何深度)。
需要注意的是 prefetch_related
不是 "free" - 它会为后面的每个关系生成一个额外的查询。 Treebeard 的查询方法通常在效率上等于或优于此 - 例如:
series = TvSeries.objects.get(id=123)
episodes = series.get_children()
将在两个查询中获取 TvSeries
及其所有剧集,就像(假设的)prefetch_related
表达式将:
# fake code, will not work...
series = TvSeries.objects.filter(id=123).prefetch_related('child_pages')
但是,get_children
的一个问题是它只会 return 基本 Page
个实例,因此需要进一步查询才能从 Episode
检索特定字段。您可以通过使用 child_of
来避免这种情况:
series = TvSeries.objects.get(id=123)
episodes = Episode.objects.child_of(series)
我面临的问题是重复的查询数量,这使得在页面模型上使用 get_parent() 或 get_children() 时应用程序变慢。如果父页面有模板中使用的图像文件,它也会增加。
所以我正在寻找一种方法来 prefetch_related 页面而不建立外键关系。
假设我有一个 TvSeries 页面模型和一个剧集页面模型:
class TvSeries(Page):
name = models.CharField()
producer = models.CharField()
subpage_types = ['Episode']
class Episode(Page):
title = models.CharField()
number = models.CharField()
parent_page_types = ['TvSeries']
查询剧集模型需要预取TvSeries!如何减少数据库调用?是否可以使用预取和 select 相关?如果是的话怎么办?如果没有,查询数量增加的解决方案是什么?
prefetch_related
不能用于 parent/child 页面关系,因为它们不使用标准的 Django ForeignKey
关系——相反,Wagtail(和 Treebeard)使用 path
字段来表示树的位置。这使得执行无法使用 ForeignKey
高效完成的查询成为可能,例如获取页面的所有后代(在任何深度)。
需要注意的是 prefetch_related
不是 "free" - 它会为后面的每个关系生成一个额外的查询。 Treebeard 的查询方法通常在效率上等于或优于此 - 例如:
series = TvSeries.objects.get(id=123)
episodes = series.get_children()
将在两个查询中获取 TvSeries
及其所有剧集,就像(假设的)prefetch_related
表达式将:
# fake code, will not work...
series = TvSeries.objects.filter(id=123).prefetch_related('child_pages')
但是,get_children
的一个问题是它只会 return 基本 Page
个实例,因此需要进一步查询才能从 Episode
检索特定字段。您可以通过使用 child_of
来避免这种情况:
series = TvSeries.objects.get(id=123)
episodes = Episode.objects.child_of(series)