Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using prefetch_related to retrieve related (parents, children pages) possible In Wagtail Pages?

The problem I am facing is duplicate number of queries which makes the app slow when using get_parent() or get_children() on Page model. which also increase if the parent page has an image file that is used in the template.

so I am looking for a way to prefetch_related pages without making a foriegn key relation.

let us say I have a TvSeries Page model and an Episode Page model:

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']

Need to prefetch the TvSeries when querying the episode model! How to reduce the database calls? Is it possible to use prefetch and select related ? if yes how?. and if not, what is the solution to the increased number of queries?

like image 473
Salman Aljabri Avatar asked Oct 19 '25 22:10

Salman Aljabri


1 Answers

prefetch_related cannot be used for parent/child page relations, because they do not use a standard Django ForeignKey relation - instead, Wagtail (and Treebeard) uses a path field to represent the tree position. This makes it possible to perform queries that can't be done efficiently with a ForeignKey, such as fetching all descendents (at any depth) of a page.

It should be noted that prefetch_related is not "free" - it will generate one extra query for every relation followed. Treebeard's query methods will usually be equal or better than this in efficiency - for example:

series = TvSeries.objects.get(id=123)
episodes = series.get_children()

will fetch a TvSeries and all of its episodes in two queries, just as a (hypothetical) prefetch_related expression would:

# fake code, will not work...
series = TvSeries.objects.filter(id=123).prefetch_related('child_pages')

However, one issue with get_children is that it will only return basic Page instances, so further queries are required to retrieve the specific fields from Episode. You can avoid this by using child_of instead:

series = TvSeries.objects.get(id=123)
episodes = Episode.objects.child_of(series)
like image 76
gasman Avatar answered Oct 22 '25 13:10

gasman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!