|
10 | 10 | from django.contrib.auth.views import redirect_to_login |
11 | 11 | from django.contrib.contenttypes.models import ContentType |
12 | 12 | from django.contrib.sites.models import Site |
| 13 | +from django.core.cache import cache |
13 | 14 | from django.core.exceptions import PermissionDenied |
14 | 15 | from django.core.paginator import EmptyPage, PageNotAnInteger |
15 | 16 | from django.db.models import Count, Exists, F, OuterRef, Q |
@@ -343,14 +344,17 @@ def question_list(request, product_slug=None, topic_slug=None): |
343 | 344 | question_qs = Question.objects.none() |
344 | 345 |
|
345 | 346 | # Top 50 tags from the pre-tag-filtered set, ordered by frequency. |
346 | | - # Force evaluation here so the template receives a plain list, avoiding |
347 | | - # lazy queryset double-evaluation issues. |
348 | | - available_tags = list( |
349 | | - Question.objects.filter(pk__in=base_qs.values("pk").distinct(), tags__isnull=False) |
350 | | - .values("tags__name", "tags__slug") |
351 | | - .annotate(count=Count("id", distinct=True)) |
352 | | - .order_by("-count")[:50] |
353 | | - ) |
| 347 | + # Cache per product/topic/locale since this query is expensive and rarely changes. |
| 348 | + _tags_cache_key = f"available_tags:{product_slug}:{topic_slug}:{request.LANGUAGE_CODE}" |
| 349 | + available_tags = cache.get(_tags_cache_key) |
| 350 | + if available_tags is None: |
| 351 | + available_tags = list( |
| 352 | + Question.objects.filter(pk__in=base_qs.values("pk").distinct(), tags__isnull=False) |
| 353 | + .values("tags__name", "tags__slug") |
| 354 | + .annotate(count=Count("id", distinct=True)) |
| 355 | + .order_by("-count")[:50] |
| 356 | + ) |
| 357 | + cache.set(_tags_cache_key, available_tags, 60 * 5) |
354 | 358 | tagged_set = set(tagged.split(",")) if tagged else set() |
355 | 359 |
|
356 | 360 | # Set the order. |
|
0 commit comments