diff --git a/kitsune/flagit/views.py b/kitsune/flagit/views.py index 2ec6b7e5fec..1517cfb0c8f 100644 --- a/kitsune/flagit/views.py +++ b/kitsune/flagit/views.py @@ -2,6 +2,7 @@ from django.contrib import messages from django.contrib.contenttypes.models import ContentType +from django.core.cache import cache from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.utils import timezone @@ -120,13 +121,43 @@ def flagged_queue(request): ) -def get_hierarchical_topics(topics, parent=None, level=0): - """Recursively build hierarchical topics.""" +def get_hierarchical_topics(product, cache_timeout=3600): + """ + Build hierarchical topics filtered by the given product. + + Args: + product: The product that should be used to filter the topics. + cache_timeout: The number of seconds to cache the result for the + given product. Defaults to 1 hour. + + Returns: + A list of dictionaries representing the hierarchical structure of topics. + """ + cache_key = f"hierarchical_topics_{product.slug}" + if cached_topics := cache.get(cache_key): + return cached_topics + + topics = list( + Topic.active.filter(products=product).order_by("title").values("id", "title", "parent_id") + ) + topic_dict = {} + for topic in topics: + parent_id = topic["parent_id"] + if parent_id not in topic_dict: + topic_dict[parent_id] = [] + topic_dict[parent_id].append(topic) + hierarchical = [] - for topic in topics.filter(parent=parent).order_by("title"): - spaces = " " * (level * 4) - hierarchical.append({"id": topic.id, "title": f"{spaces}{topic.title}"}) - hierarchical.extend(get_hierarchical_topics(topics, parent=topic, level=level + 1)) + + def build_hierarchy(parent_id=None, level=0): + children = topic_dict.get(parent_id, []) + for child in children: + spaces = " " * (level * 4) + hierarchical.append({"id": child["id"], "title": f"{spaces}{child['title']}"}) + build_hierarchy(child["id"], level + 1) + + build_hierarchy() + cache.set(cache_key, hierarchical, cache_timeout) return hierarchical @@ -152,8 +183,7 @@ def moderate_content(request): for obj in objects: question = obj.content_object - all_topics = Topic.active.filter(is_archived=False, products=question.product) - obj.available_topics = get_hierarchical_topics(all_topics) + obj.available_topics = get_hierarchical_topics(question.product) obj.available_tags = available_tags obj.saved_tags = question.tags.values_list("id", flat=True) return render(