Skip to content

Commit 94ec489

Browse files
committed
Merge branch 'fix/twe-50-blogpage-related-posts-same-division' into staging
2 parents 0e855be + e66cabd commit 94ec489

File tree

6 files changed

+117
-23
lines changed

6 files changed

+117
-23
lines changed

.github/pull_request_template.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464

6565
- [ ] Images are optimised and lazy-loading used where appropriate
6666
- [ ] SVGs have been optimised
67-
- [ ] Perfomance and transfer of data considered
67+
- [ ] Performance and transfer of data considered
6868
- [ ] If JavaScript is needed alternatives have been considered
6969
- [ ] Not required
7070

tbx/blog/models.py

+23-10
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ def services(self):
169169
def tags(self):
170170
return chain(self.services, self.sectors)
171171

172-
@cached_property
173-
def related_blog_posts(self):
172+
def get_related_blog_posts(self):
174173
prefetch_author_images = models.Prefetch(
175174
"authors__author__image",
176175
queryset=CustomImage.objects.prefetch_renditions(
@@ -179,13 +178,8 @@ def related_blog_posts(self):
179178
"format-webp|fill-286x286",
180179
),
181180
)
182-
183-
return (
184-
BlogPage.objects.filter(
185-
Q(related_sectors__in=self.sectors)
186-
| Q(related_services__in=self.services)
187-
)
188-
.live()
181+
queryset = (
182+
BlogPage.objects.live()
189183
.public()
190184
.defer_streamfields()
191185
.prefetch_related(
@@ -196,9 +190,28 @@ def related_blog_posts(self):
196190
)
197191
.distinct()
198192
.order_by("-date")
199-
.exclude(pk=self.pk)[:3]
193+
.exclude(pk=self.pk)
200194
)
201195

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+
211+
@cached_property
212+
def related_blog_posts(self):
213+
return self.get_related_blog_posts()[:3]
214+
202215
@cached_property
203216
def blog_index(self):
204217
ancestor = BlogIndexPage.objects.ancestor_of(self).order_by("-depth").first()

tbx/blog/tests/test_models.py

+32
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
from operator import attrgetter
2+
13
from django.core.paginator import Page as PaginatorPage
24

35
from wagtail.coreutils import get_dummy_request
46
from wagtail.models import PageViewRestriction
57
from wagtail.test.utils import WagtailPageTestCase
68

79
from faker import Faker
10+
from wagtail_factories import PageFactory
811

912
from tbx.blog.factories import BlogIndexPageFactory, BlogPageFactory
1013
from tbx.blog.models import BlogPage
14+
from tbx.divisions.factories import DivisionPageFactory
1115
from tbx.taxonomy.factories import SectorFactory, ServiceFactory
1216

1317

@@ -59,3 +63,31 @@ def test_create(self):
5963
)
6064
self.assertEqual(another_blog_post.related_services.count(), 3)
6165
self.assertEqual(another_blog_post.related_sectors.count(), 2)
66+
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)
83+
84+
self.assertQuerySetEqual(
85+
blog_post.related_blog_posts,
86+
[
87+
"same division (direct)",
88+
"same division (direct) same sector",
89+
"same division (parent)",
90+
],
91+
transform=attrgetter("title"),
92+
ordered=False,
93+
)

tbx/project_styleguide/templates/patterns/molecules/carbon-impact/carbon-impact.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="grid">
55
<div class="grid__carbon-impact">
66
<div class="footer__carbon-impact">
7-
<p class="footer__carbon-impact-text">Loading the site homepage emits just <span>0.07g of CO2</span> per view.</p>
7+
<p class="footer__carbon-impact-text">Loading the site homepage emits just <span>0.02g of CO2</span> per view.</p>
88
{% if CARBON_EMISSIONS_PAGE %}
99
<p class="footer__carbon-impact-text">
1010
<a href="{% pageurl CARBON_EMISSIONS_PAGE %}" class="footer__carbon-impact-link">Find out more about our carbon impact</a>

tbx/work/models.py

+24-10
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,7 @@ def header_image_alt_text(self):
298298
return header_alt_text
299299
return self.header_image.title
300300

301-
@property
302-
def related_works(self):
301+
def get_related_works(self):
303302
prefetch_listing_images = models.Prefetch(
304303
"header_image",
305304
queryset=CustomImage.objects.prefetch_renditions(
@@ -310,23 +309,38 @@ def related_works(self):
310309
),
311310
)
312311

313-
# get 3 pages with same services and exclude self page
314-
return (
315-
WorkPage.objects.filter(
316-
Q(related_sectors__in=self.sectors)
317-
| Q(related_services__in=self.services)
318-
)
319-
.live()
312+
queryset = (
313+
WorkPage.objects.live()
320314
.public()
321315
.defer_streamfields()
322316
.prefetch_related(
323317
"related_sectors", "related_services", prefetch_listing_images
324318
)
325319
.distinct()
326320
.order_by(F("date").desc(nulls_last=True))
327-
.exclude(pk=self.pk)[:3]
321+
.exclude(pk=self.pk)
328322
)
329323

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+
339+
@cached_property
340+
def related_works(self):
341+
# get 3 pages with same services and exclude self page
342+
return self.get_related_works()[:3]
343+
330344
def set_body_word_count(self):
331345
body_basic_html = self.body.stream_block.render_basic(self.body)
332346
body_text = BeautifulSoup(body_basic_html, "html.parser").get_text()

tbx/work/tests/test_models.py

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
from operator import attrgetter
2+
13
from django.core.paginator import Page as PaginatorPage
24

35
from wagtail.coreutils import get_dummy_request
46
from wagtail.models import PageViewRestriction
57
from wagtail.test.utils import WagtailPageTestCase
68

7-
from tbx.taxonomy.factories import ServiceFactory
9+
from wagtail_factories import PageFactory
10+
11+
from tbx.divisions.factories import DivisionPageFactory
12+
from tbx.taxonomy.factories import SectorFactory, ServiceFactory
813
from tbx.work.factories import (
914
HistoricalWorkPageFactory,
1015
WorkIndexPageFactory,
@@ -55,6 +60,36 @@ def test_create(self):
5560
self.assertEqual(another_page.related_services.count(), 3)
5661

5762

63+
class TestWorkPage(WagtailPageTestCase):
64+
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)
80+
81+
self.assertQuerySetEqual(
82+
work_page.related_works,
83+
[
84+
"same division (direct)",
85+
"same division (direct) same sector",
86+
"same division (parent)",
87+
],
88+
transform=attrgetter("title"),
89+
ordered=False,
90+
)
91+
92+
5893
class TestWorkPageFactory(WagtailPageTestCase):
5994
def test_create(self):
6095
page = WorkPageFactory()

0 commit comments

Comments
 (0)