Skip to content

Commit bfff176

Browse files
authored
Merge pull request #386 from torchbox/fix/slow-blog-posts
Fix slow blog posts
2 parents 380e689 + f3f77f7 commit bfff176

File tree

5 files changed

+54
-86
lines changed

5 files changed

+54
-86
lines changed

tbx/blog/models.py

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -178,36 +178,19 @@ def get_related_blog_posts(self):
178178
"format-webp|fill-286x286",
179179
),
180180
)
181-
queryset = (
182-
BlogPage.objects.live()
181+
return (
182+
# Assumption that blog posts for the same division
183+
# will be under the same blog index page.
184+
BlogPage.objects.sibling_of(self)
185+
.live()
183186
.public()
184187
.defer_streamfields()
185-
.prefetch_related(
186-
"authors__author",
187-
"related_sectors",
188-
"related_services",
189-
prefetch_author_images,
190-
)
188+
.prefetch_related("authors__author", prefetch_author_images)
191189
.distinct()
192190
.order_by("-date")
193191
.exclude(pk=self.pk)
194192
)
195193

196-
if final_division := getattr(self, "final_division", None):
197-
# Ideally this would be implemented at the database-level but it's
198-
# very hard to implement the final_division logic at the ORM level
199-
def filter_fn(page):
200-
return page.final_division == final_division
201-
202-
queryset = list(filter(filter_fn, queryset))
203-
else:
204-
queryset = queryset.filter(
205-
Q(related_sectors__in=self.sectors)
206-
| Q(related_services__in=self.services)
207-
)
208-
209-
return queryset
210-
211194
@cached_property
212195
def related_blog_posts(self):
213196
return self.get_related_blog_posts()[:3]

tbx/blog/tests/test_models.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
from django.core.paginator import Page as PaginatorPage
44

55
from wagtail.coreutils import get_dummy_request
6-
from wagtail.models import PageViewRestriction
6+
from wagtail.models import PageViewRestriction, Site
77
from wagtail.test.utils import WagtailPageTestCase
88

99
from faker import Faker
10-
from wagtail_factories import PageFactory
1110

1211
from tbx.blog.factories import BlogIndexPageFactory, BlogPageFactory
1312
from tbx.blog.models import BlogPage
13+
from tbx.core.factories import HomePageFactory
1414
from tbx.divisions.factories import DivisionPageFactory
1515
from tbx.taxonomy.factories import SectorFactory, ServiceFactory
1616

@@ -64,29 +64,28 @@ def test_create(self):
6464
self.assertEqual(another_blog_post.related_services.count(), 3)
6565
self.assertEqual(another_blog_post.related_sectors.count(), 2)
6666

67-
def test_related_blog_posts_same_division(self):
68-
sector = SectorFactory.create()
69-
# The logic of `final_division` skips ancestors with depth <= 2,
70-
# So we create the division page with enough parents to be at depth 3:
71-
division = DivisionPageFactory.create(parent=PageFactory(parent=PageFactory()))
72-
blog_post = BlogPageFactory(division=division, related_sectors=[sector])
73-
BlogPageFactory(title="same sector", division=None, related_sectors=[sector])
74-
BlogPageFactory(
75-
title="same division (direct)", division=division, related_sectors=[]
76-
)
77-
BlogPageFactory(
78-
title="same division (direct) same sector",
79-
division=division,
80-
related_sectors=[sector],
81-
)
82-
BlogPageFactory(title="same division (parent)", parent=division)
67+
68+
class TestBlogPage(WagtailPageTestCase):
69+
def test_related_blog_posts(self):
70+
site = Site.objects.get(is_default_site=True)
71+
root = site.root_page.specific
72+
homepage = HomePageFactory(parent=root)
73+
division = DivisionPageFactory(parent=homepage, title="Charity")
74+
blog_index = BlogIndexPageFactory(parent=division)
75+
76+
other_division = DivisionPageFactory(parent=homepage, title="Public")
77+
other_index = BlogIndexPageFactory(parent=other_division)
78+
BlogPageFactory(parent=other_index)
79+
80+
blog_post = BlogPageFactory(parent=blog_index, title="Blog Post 1")
81+
BlogPageFactory(parent=blog_index, title="Blog Post 2")
82+
BlogPageFactory(parent=blog_index, title="Blog Post 3")
8383

8484
self.assertQuerySetEqual(
8585
blog_post.related_blog_posts,
8686
[
87-
"same division (direct)",
88-
"same division (direct) same sector",
89-
"same division (parent)",
87+
"Blog Post 2",
88+
"Blog Post 3",
9089
],
9190
transform=attrgetter("title"),
9291
ordered=False,

tbx/taxonomy/tests/test_models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from unittest import skip
2+
13
from wagtail.models import Site
24
from wagtail.test.utils import WagtailPageTestCase
35

@@ -78,6 +80,7 @@ def test_blog_post_taxonomies_tags(self):
7880
self.assertListEqual(list(self.blog_page_service.tags), [services[1]])
7981
self.assertListEqual(list(self.blog_page_sector.tags), [sectors[1]])
8082

83+
@skip("Related services in blog posts are currently disabled")
8184
def test_related_blog_posts_services(self):
8285
"""
8386
Tests the `related_blog_posts` property on the `BlogPage` model using the Service taxonomy
@@ -104,6 +107,7 @@ def test_related_blog_posts_services(self):
104107
# so there should be 3 related blog posts
105108
self.assertEqual(len(blog_post3.related_blog_posts), 3)
106109

110+
@skip("Related sectors in blog posts are currently disabled")
107111
def test_related_blog_posts_sectors(self):
108112
"""
109113
Tests the `related_blog_posts` property on the `BlogPage` model using the Sectors taxonomy

tbx/work/models.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -309,33 +309,19 @@ def get_related_works(self):
309309
),
310310
)
311311

312-
queryset = (
313-
WorkPage.objects.live()
312+
return (
313+
# Assumption that work pages for the same division
314+
# will be under the same work index page.
315+
WorkPage.objects.sibling_of(self)
316+
.live()
314317
.public()
315318
.defer_streamfields()
316-
.prefetch_related(
317-
"related_sectors", "related_services", prefetch_listing_images
318-
)
319+
.prefetch_related(prefetch_listing_images)
319320
.distinct()
320321
.order_by(F("date").desc(nulls_last=True))
321322
.exclude(pk=self.pk)
322323
)
323324

324-
if final_division := getattr(self, "final_division", None):
325-
# Ideally this would be implemented at the database-level but it's
326-
# very hard to implement the final_division logic at the ORM level
327-
def filter_fn(page):
328-
return page.final_division == final_division
329-
330-
queryset = list(filter(filter_fn, queryset))
331-
else:
332-
queryset = queryset.filter(
333-
Q(related_sectors__in=self.sectors)
334-
| Q(related_services__in=self.services)
335-
)
336-
337-
return queryset
338-
339325
@cached_property
340326
def related_works(self):
341327
# get 3 pages with same services and exclude self page

tbx/work/tests/test_models.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
from django.core.paginator import Page as PaginatorPage
44

55
from wagtail.coreutils import get_dummy_request
6-
from wagtail.models import PageViewRestriction
6+
from wagtail.models import PageViewRestriction, Site
77
from wagtail.test.utils import WagtailPageTestCase
88

9-
from wagtail_factories import PageFactory
10-
9+
from tbx.core.factories import HomePageFactory
1110
from tbx.divisions.factories import DivisionPageFactory
12-
from tbx.taxonomy.factories import SectorFactory, ServiceFactory
11+
from tbx.taxonomy.factories import ServiceFactory
1312
from tbx.work.factories import (
1413
HistoricalWorkPageFactory,
1514
WorkIndexPageFactory,
@@ -62,28 +61,25 @@ def test_create(self):
6261

6362
class TestWorkPage(WagtailPageTestCase):
6463
def test_related_works(self):
65-
sector = SectorFactory.create()
66-
# The logic of `final_division` skips ancestors with depth <= 2,
67-
# So we create the division page with enough parents to be at depth 3:
68-
division = DivisionPageFactory.create(parent=PageFactory(parent=PageFactory()))
69-
work_page = WorkPageFactory(division=division, related_sectors=[sector])
70-
WorkPageFactory(title="same sector", division=None, related_sectors=[sector])
71-
WorkPageFactory(
72-
title="same division (direct)", division=division, related_sectors=[]
73-
)
74-
WorkPageFactory(
75-
title="same division (direct) same sector",
76-
division=division,
77-
related_sectors=[sector],
78-
)
79-
WorkPageFactory(title="same division (parent)", parent=division)
64+
site = Site.objects.get(is_default_site=True)
65+
root = site.root_page.specific
66+
homepage = HomePageFactory(parent=root)
67+
division = DivisionPageFactory(parent=homepage, title="Charity")
68+
work_index = WorkIndexPageFactory(parent=division)
69+
70+
other_division = DivisionPageFactory(parent=homepage, title="Public")
71+
other_index = WorkIndexPageFactory(parent=other_division)
72+
WorkPageFactory(parent=other_index)
73+
74+
work_page = WorkPageFactory(parent=work_index, title="Work Page 1")
75+
WorkPageFactory(parent=work_index, title="Work Page 2")
76+
WorkPageFactory(parent=work_index, title="Work Page 3")
8077

8178
self.assertQuerySetEqual(
8279
work_page.related_works,
8380
[
84-
"same division (direct)",
85-
"same division (direct) same sector",
86-
"same division (parent)",
81+
"Work Page 2",
82+
"Work Page 3",
8783
],
8884
transform=attrgetter("title"),
8985
ordered=False,

0 commit comments

Comments
 (0)