in kitsune/wiki/utils.py [0:0]
def build_topics_data(request: HttpRequest, product: Product, topics: list[Topic]) -> list[dict]:
"""Build topics_data for use in topic cards
Args:
request: HttpRequest - The current request
product: Product - The product to get topics for
topics: list[Topic] - List of topics to process
Returns:
list[dict]: List of topic data dictionaries containing:
- topic: Topic object
- topic_url: URL to topic's documents
- title: Topic title
- total_articles: Combined count of main and fallback articles
- image_url: Topic image URL
- documents: Up to 3 documents to display
"""
topics_data: list[dict] = []
featured_articles = get_featured_articles(product, locale=request.LANGUAGE_CODE, topics=topics)
# Get both main and fallback documents from the faceted search
main_docs_data, fallback_docs_data = documents_for(
request.user, request.LANGUAGE_CODE, topics=topics, products=[product]
)
main_doc_ids = {doc["id"] for doc in main_docs_data}
fallback_doc_ids = {doc["id"] for doc in (fallback_docs_data or [])}
all_documents = (
Document.objects.filter(id__in=main_doc_ids | fallback_doc_ids)
.select_related("parent")
.prefetch_related(
"topics",
"parent__topics",
)
)
# topic_id -> (main_docs, fallback_docs) mapping
topic_docs_map: dict[int, tuple[list[Document], list[Document]]] = {
topic.id: ([], []) for topic in topics
}
doc_topics_map: dict[int, list[Topic]] = {}
for doc in all_documents:
doc_topics = set(doc.parent.topics.all()) if doc.parent else set(doc.topics.all())
doc_topics_map[doc.id] = list(doc_topics)
for topic in doc_topics:
if topic.id in topic_docs_map:
main_list, fallback_list = topic_docs_map[topic.id]
target_list = main_list if doc.id in main_doc_ids else fallback_list
target_list.append(doc)
for topic in topics:
main_topic_docs, fallback_topic_docs = topic_docs_map[topic.id]
if not main_topic_docs and not fallback_topic_docs:
continue
topic_featured = [
doc
for doc in featured_articles
if doc.id in doc_topics_map and any(t.id == topic.id for t in doc_topics_map[doc.id])
]
# Get remaining main documents excluding featured ones
remaining_docs = (doc for doc in main_topic_docs if doc not in topic_featured)
# First try to get documents from featured and main docs
main_docs = list(islice(chain(topic_featured, remaining_docs), 3))
# Fall back to fallback documents only if no main documents exist
documents_to_show = main_docs if main_docs else list(islice(fallback_topic_docs, 3))
topic_data = {
"topic": topic,
"topic_url": reverse("products.documents", args=[product.slug, topic.slug]),
"title": topic.title,
"total_articles": len(main_topic_docs) + len(fallback_topic_docs),
"image_url": topic.image_url,
"documents": documents_to_show,
}
topics_data.append(topic_data)
return topics_data