in kitsune/wiki/views.py [0:0]
def document(request, document_slug, document=None):
"""View a wiki document."""
fallback_reason = None
full_locale_name = None
vary_on_accept_language = False
def maybe_vary_on_accept_language(response):
"""
Patch the VARY header in the response to include "Accept-Language"
if the Accept-Language header could vary the response, and return
the response.
"""
if vary_on_accept_language:
patch_vary_headers(response, ["accept-language"])
return response
doc = get_visible_document_or_404(
request.user,
locale=request.LANGUAGE_CODE,
slug=document_slug,
look_for_translation_via_parent=True,
return_parent_if_no_translation=True,
)
if doc.slug != document_slug:
# We've found the translation at a different slug.
url = doc.get_absolute_url()
url = urlparams(url, query_dict=request.GET)
return HttpResponseRedirect(url)
if doc.locale != request.LANGUAGE_CODE:
# The "doc" is the parent document.
if doc.current_revision:
# Check for unapproved revisions
unapproved_translation_exists = Revision.objects.filter(
is_approved=False,
document__parent=doc,
document__locale=request.LANGUAGE_CODE,
).exists()
if unapproved_translation_exists:
fallback_reason = "translation_not_approved"
else:
# There is no translation, so we'll fall back to its approved parent,
# unless we find an approved translation in a fallback locale.
fallback_reason = "no_translation"
# Find and show the defined fallback locale rather than the English
# version of the document. The fallback locale is defined based on
# the ACCEPT_LANGUAGE header, site-wide locale mapping and custom
# fallback locale. The custom fallback locale is defined in the
# FALLBACK_LOCALES array in kitsune/wiki/config.py. See bug 800880
# for more details
fallback_locale, vary_on_accept_language = get_fallback_locale(doc, request)
# If a fallback locale is defined, show the document in that locale,
# otherwise continue with the document in the default language.
if fallback_locale:
# If we have a fallback locale, it means we're guaranteed to have
# a translation in that locale with approved content.
doc = doc.translated_to(fallback_locale)
# For showing the fallback locale explanation message to the user
fallback_reason = "fallback_locale"
full_locale_name = {
request.LANGUAGE_CODE: LOCALES[request.LANGUAGE_CODE].native,
fallback_locale: LOCALES[fallback_locale].native,
}
if not doc.current_revision:
# We've got a document, but it has no approved content.
if doc.parent and doc.parent.current_revision:
# The "doc" is a translation with no approved content, but its
# parent has approved content, so let's fall back to its parent.
fallback_reason = "translation_not_approved"
else:
# We can't find any approved content to show.
fallback_reason = "no_content"
any_localizable_revision = doc.revisions.filter(
is_approved=True, is_ready_for_localization=True
).exists()
# Obey explicit redirect pages:
# Don't redirect on redirect=no (like Wikipedia), so we can link from a
# redirected-to-page back to a "Redirected from..." link, so you can edit
# the redirect.
redirect_url = (
None if request.GET.get("redirect") == "no" else doc.redirect_url(request.LANGUAGE_CODE)
)
if redirect_url:
url = urlparams(
redirect_url, query_dict=request.GET, redirectslug=doc.slug, redirectlocale=doc.locale
)
return maybe_vary_on_accept_language(HttpResponseRedirect(url))
# Get "redirected from" doc if we were redirected:
redirect_slug = request.GET.get("redirectslug")
redirect_locale = request.GET.get("redirectlocale")
redirected_from = None
if redirect_slug and redirect_locale:
try:
redirected_from = Document.objects.get_visible(
request.user, locale=redirect_locale, slug=redirect_slug
)
except Document.DoesNotExist:
pass
contributors = doc.contributors.all()
products = doc.get_products()
if len(products) < 1:
product = Product.active.filter(visible=True)[0]
else:
product = products.first()
# Set the AAQ context for the widget
set_aaq_context(request, product, multiple_products=len(products) > 1)
product_topics = Topic.active.filter(products=product, visible=True)
# Create serialized versions of the document's associated products and topics
# to be used within GA as parameters/dimensions.
ga_products = f"/{'/'.join(products.order_by('slug').values_list('slug', flat=True))}/"
ga_topics = f"/{'/'.join(doc.get_topics().order_by('slug').values_list('slug', flat=True))}/"
# Provide the actual locale of the document that will also be used as a GA parameter/dimension.
ga_article_locale = (
doc.parent.locale
if (fallback_reason == "translation_not_approved") and doc.parent
else doc.locale
)
# Switching devices section
switching_devices_product = switching_devices_topic = switching_devices_subtopics = None
if doc.is_switching_devices_document:
# make sure that the article is in the right product and topic
if (
not products.filter(slug="firefox").exists()
or not product_topics.filter(slug=settings.FIREFOX_SWITCHING_DEVICES_TOPIC).exists()
):
raise Http404
switching_devices_product = Product.active.get(slug="firefox")
switching_devices_topic = Topic.active.get(
products=switching_devices_product, slug=settings.FIREFOX_SWITCHING_DEVICES_TOPIC
)
switching_devices_subtopics = topics_for(
request.user, product=switching_devices_product, parent=switching_devices_topic
)
if document_slug in COLLAPSIBLE_DOCUMENTS.get(request.LANGUAGE_CODE, []):
document_css_class = "collapsible"
else:
document_css_class = ""
# Build a set of breadcrumbs, ending with the document's title, and
# starting with the product, with the topic(s) in between.
# The breadcrumbs are built backwards, and then reversed.
# Get document title. If it is like "Title - Subtitle", strip off the subtitle.
trimmed_title = doc.title.split(" - ")[0].strip()
breadcrumbs = [(None, trimmed_title)]
# Get the dominant topic, and all parent topics. Save the topic chosen for
# picking a product later.
document_topics = doc.get_topics().order_by("display_order")
if len(document_topics) > 0:
topic = document_topics.first()
breadcrumbs.append((topic.get_absolute_url(product.slug), topic.title))
breadcrumbs.append((product.get_absolute_url(), product.title))
# The list above was built backwards, so flip this.
breadcrumbs.reverse()
votes = HelpfulVote.objects.filter(revision=doc.current_revision).aggregate(
total_votes=Count("id"),
helpful_votes=Count("id", filter=Q(helpful=True)),
)
helpful_votes = (
int((votes["helpful_votes"] / votes["total_votes"]) * 100)
if votes["total_votes"] > 0
else 0
)
is_first_revision = doc.revisions.filter(is_approved=True).count() == 1
show_aaq_widget = (
not (doc.parent and doc.parent.slug == "get-community-support")
and doc.slug != "get-community-support"
)
update_kb_visited(request.session, doc)
data = {
"document": doc,
"is_first_revision": is_first_revision,
"redirected_from": redirected_from,
"contributors": contributors,
"fallback_reason": fallback_reason,
"helpful_votes": helpful_votes,
"product_topics": product_topics,
"product": product,
"products": products,
"ga_topics": ga_topics,
"ga_products": ga_products,
"ga_article_locale": ga_article_locale,
"related_products": doc.related_products.exclude(pk=product.pk),
"show_aaq_widget": show_aaq_widget,
"breadcrumb_items": breadcrumbs,
"document_css_class": document_css_class,
"any_localizable_revision": any_localizable_revision,
"full_locale_name": full_locale_name,
"switching_devices_product": switching_devices_product,
"switching_devices_topic": switching_devices_topic,
"switching_devices_subtopics": switching_devices_subtopics,
"product_titles": ", ".join(p.title for p in sorted(products, key=lambda p: p.title)),
}
return maybe_vary_on_accept_language(render(request, "wiki/document.html", data))