From f47a4ae1d3d09d81d4afd50c503e1e4134b0718f Mon Sep 17 00:00:00 2001 From: Dan Braghis Date: Thu, 13 Jan 2022 20:15:51 +0000 Subject: [PATCH] Improve locale_label_from_id caching --- .../admin/templatetags/wagtailadmin_tags.py | 18 ++++-------------- wagtail/admin/tests/test_templatetags.py | 11 +++-------- wagtail/core/signal_handlers.py | 10 +++++++++- wagtail/core/utils.py | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/wagtail/admin/templatetags/wagtailadmin_tags.py b/wagtail/admin/templatetags/wagtailadmin_tags.py index 66bebbf0ed..815a0c4581 100644 --- a/wagtail/admin/templatetags/wagtailadmin_tags.py +++ b/wagtail/admin/templatetags/wagtailadmin_tags.py @@ -40,7 +40,7 @@ from wagtail.core.models import ( from wagtail.core.telepath import JSContext from wagtail.core.utils import camelcase_to_underscore from wagtail.core.utils import cautious_slugify as _cautious_slugify -from wagtail.core.utils import escape_script, get_content_type_label +from wagtail.core.utils import escape_script, get_content_type_label, get_locales_display_names from wagtail.users.utils import get_gravatar_url @@ -766,22 +766,12 @@ def locales(): ]) -@register.simple_tag(takes_context=True) -def locale_label_from_id(context, locale_id): +@register.simple_tag +def locale_label_from_id(locale_id): """ Returns the Locale display name given its id. """ - request = context['request'] - - # Cache the locale id -> locale display name mapping on the request - if not hasattr(request, '_wagtail_locales'): - locales_map = {} - for locale in Locale.objects.all(): - locales_map[locale.pk] = locale.get_display_name() - setattr(request, '_wagtail_locales', locales_map) - context['request'] = request - - return context['request']._wagtail_locales.get(locale_id) + return get_locales_display_names().get(locale_id) @register.simple_tag() diff --git a/wagtail/admin/tests/test_templatetags.py b/wagtail/admin/tests/test_templatetags.py index ee0fa6ccf4..9b968db404 100644 --- a/wagtail/admin/tests/test_templatetags.py +++ b/wagtail/admin/tests/test_templatetags.py @@ -4,7 +4,6 @@ from datetime import timedelta from unittest import mock from django.conf import settings -from django.http import HttpRequest from django.template import Context, Template from django.test import TestCase from django.test.utils import override_settings @@ -196,16 +195,12 @@ class TestInternationalisationTags(TestCase): ) def test_locale_label_from_id(self): - context = { - "request": HttpRequest() - } - with self.assertNumQueries(1): - self.assertEqual(locale_label_from_id(context, self.locale_ids[0]), "English") + self.assertEqual(locale_label_from_id(self.locale_ids[0]), "English") with self.assertNumQueries(0): - self.assertEqual(locale_label_from_id(context, self.locale_ids[1]), "French") + self.assertEqual(locale_label_from_id(self.locale_ids[1]), "French") # check with an invalid id with self.assertNumQueries(0): - self.assertIsNone(locale_label_from_id(context, self.locale_ids[-1] + 100), None) + self.assertIsNone(locale_label_from_id(self.locale_ids[-1] + 100), None) diff --git a/wagtail/core/signal_handlers.py b/wagtail/core/signal_handlers.py index d8f7c94d4f..e9f79225ea 100644 --- a/wagtail/core/signal_handlers.py +++ b/wagtail/core/signal_handlers.py @@ -3,7 +3,8 @@ import logging from django.core.cache import cache from django.db.models.signals import post_delete, post_save, pre_delete -from wagtail.core.models import Page, Site +from wagtail.core.models import Locale, Page, Site +from wagtail.core.utils import get_locales_display_names logger = logging.getLogger('wagtail.core') @@ -29,9 +30,16 @@ def post_delete_page_log_deletion(sender, instance, **kwargs): logger.info("Page deleted: \"%s\" id=%d", instance.title, instance.id) +def reset_locales_display_names_cache(sender, instance, **kwargs): + get_locales_display_names.cache_clear() + + def register_signal_handlers(): post_save.connect(post_save_site_signal_handler, sender=Site) post_delete.connect(post_delete_site_signal_handler, sender=Site) pre_delete.connect(pre_delete_page_unpublish, sender=Page) post_delete.connect(post_delete_page_log_deletion, sender=Page) + + post_save.connect(reset_locales_display_names_cache, sender=Locale) + post_delete.connect(reset_locales_display_names_cache, sender=Locale) diff --git a/wagtail/core/utils.py b/wagtail/core/utils.py index a74eeeb59e..712cebbc68 100644 --- a/wagtail/core/utils.py +++ b/wagtail/core/utils.py @@ -309,6 +309,20 @@ def get_supported_content_language_variant(lang_code, strict=False): raise LookupError(lang_code) +@functools.lru_cache() +def get_locales_display_names() -> dict: + """ + Cache of the locale id -> locale display name mapping + """ + from wagtail.core.models import Locale # inlined to avoid circular imports + + locales_map = { + locale.pk: locale.get_display_name() + for locale in Locale.objects.all() + } + return locales_map + + @receiver(setting_changed) def reset_cache(**kwargs): """