diff --git a/Makefile b/Makefile index 70ab30dfa..77c976d48 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ help: ## Display this help text mkdir -p .state && touch .state/db-migrated .state/db-initialized: .state/docker-build-web .state/db-migrated + docker compose run --rm web ./manage.py createcachetable docker compose run --rm web ./manage.py loaddata fixtures/*.json mkdir -p .state && touch .state/db-initialized diff --git a/apps/sponsors/tests/test_models.py b/apps/sponsors/tests/test_models.py index 24d5ecf26..c5a71ad68 100644 --- a/apps/sponsors/tests/test_models.py +++ b/apps/sponsors/tests/test_models.py @@ -6,7 +6,7 @@ from django.core.cache import cache from django.core.mail import EmailMessage from django.db import IntegrityError -from django.test import TestCase +from django.test import TestCase, override_settings from django.utils import timezone from model_bakery import baker, seq @@ -327,6 +327,14 @@ def test_singleton_object_cannot_be_deleted(self): self.assertIn("Singleton object cannot be delete. Try updating it instead.", str(context.exception)) + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + "LOCATION": "pythondotorg-local-cache", + } + } + ) def test_current_year_is_cached(self): # cleans cached from previous test runs cache.clear() diff --git a/pydotorg/apps.py b/pydotorg/apps.py new file mode 100644 index 000000000..4b823818b --- /dev/null +++ b/pydotorg/apps.py @@ -0,0 +1,13 @@ +"""Core pydotorg application configuration.""" + +from django.apps import AppConfig + + +class PyDotOrgConfig(AppConfig): + """AppConfig for the pydotorg core application.""" + + name = "pydotorg" + + def ready(self): + """Register signal handlers.""" + import pydotorg.signals # noqa: F401 diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 81b3f4d3e..5d3f53f86 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -195,6 +195,7 @@ "widget_tweaks", "django_countries", "sorl.thumbnail", + "pydotorg", "apps.banners", "apps.blogs", "apps.boxes", diff --git a/pydotorg/settings/local.py b/pydotorg/settings/local.py index c853fcbad..e93395bc5 100644 --- a/pydotorg/settings/local.py +++ b/pydotorg/settings/local.py @@ -41,8 +41,8 @@ CACHES = { "default": { - "BACKEND": "django.core.cache.backends.locmem.LocMemCache", - "LOCATION": "pythondotorg-local-cache", + "BACKEND": "django.core.cache.backends.db.DatabaseCache", + "LOCATION": "django_cache_table", } } diff --git a/pydotorg/signals.py b/pydotorg/signals.py new file mode 100644 index 000000000..e17934562 --- /dev/null +++ b/pydotorg/signals.py @@ -0,0 +1,17 @@ +"""Signal handlers for sitetree cache invalidation.""" + +from django.db.models.signals import m2m_changed, post_delete, post_save +from django.dispatch import receiver +from sitetree.models import Tree, TreeItem +from sitetree.sitetreeapp import get_sitetree + + +@receiver(post_save, sender=Tree) +@receiver(post_save, sender=TreeItem) +@receiver(post_delete, sender=TreeItem) +@receiver(m2m_changed, sender=TreeItem.access_permissions) +def purge_sitetree_cache(sender, instance, **kwargs): + """Purge sitetree cache on tree or item changes for cross-process invalidation.""" + cache_ = get_sitetree().cache + cache_.empty() + cache_.reset()