Add start of simple module to help with caching singleton URLs

This commit is contained in:
Jake Howard 2022-08-28 17:42:21 +01:00
parent 557a28833b
commit ac46c0ae0b
Signed by: jake
GPG Key ID: 57AFB45680EDD477
5 changed files with 65 additions and 0 deletions

View File

@ -0,0 +1,16 @@
from django.test import TestCase
from website.common.models import ContentPage
from website.home.models import HomePage
from .utils import SingletonURLCache
class SingletonURLTestCase(TestCase):
def test_gets_url(self) -> None:
with self.assertNumQueries(2):
self.assertEqual(SingletonURLCache.get_url(HomePage), "http://localhost/")
def test_missing_page(self) -> None:
with self.assertNumQueries(1):
self.assertIsNone(SingletonURLCache.get_url(ContentPage))

View File

@ -0,0 +1,32 @@
from typing import Type
from django.core.cache import cache
from django.http.request import HttpRequest
from wagtail.models import Page
class SingletonURLCache:
@classmethod
def get_url_cache_key(cls, model: Type[Page]) -> str:
return f"singleton_url_{model.__name__}"
@classmethod
def get_url(
cls, model: Type[Page], request: HttpRequest | None = None
) -> str | None:
cache_key = cls.get_url_cache_key(model)
url = cache.get(cache_key)
if url is None:
# `.first` is marginally more efficient than `.get`
page = Page.objects.type(model).first()
if page is None:
return None
url = page.get_full_url(request)
cache.set(cache_key, url, 86400)
return url

View File

@ -0,0 +1,16 @@
from django.core.cache import cache
from wagtail import hooks
from website.common.utils import get_page_models
from .utils import SingletonURLCache
@hooks.register("after_move_page")
def clear_singleton_url_cache(**kwargs: dict) -> None:
"""
Clear all page caches, in case a parent has moved
"""
cache.delete_many(
[SingletonURLCache.get_url_cache_key(model) for model in get_page_models()]
)

View File

@ -41,6 +41,7 @@ INSTALLED_APPS = [
"website.contrib.code_block",
"website.contrib.mermaid_block",
"website.contrib.unsplash",
"website.contrib.singleton_url",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.contrib.modeladmin",