diff --git a/djangoproject/scss/_style.scss b/djangoproject/scss/_style.scss index 73edaa276..f6baff1d3 100644 --- a/djangoproject/scss/_style.scss +++ b/djangoproject/scss/_style.scss @@ -2578,6 +2578,40 @@ table.docutils th { } } +search.filters { + @include sans-serif; + + display: flex; + gap: 10px; + border-bottom: 2px solid var(--hairline-color); + overflow-x: auto; + white-space: nowrap; + padding-bottom: 0; + position: relative; + + a { + padding: 10px 20px; + text-decoration: none; + border-bottom: 3px solid transparent; + transition: color 0.3s ease, border-bottom 0.3s ease; + color: var(--text-light); + flex-shrink: 0; + + &:not([href]) { + color: var(--body-fg); + font-weight: bold; + border-bottom: 3px solid var(--primary); + } + + &[href]:focus, + &[href]:active, + &[href]:hover { + outline: none; + border-bottom: 3px solid var(--hairline-color); + } + } +} + .search-links { @extend .list-links; diff --git a/docs/models.py b/docs/models.py index 8ff9a50f7..fb6714b9b 100644 --- a/docs/models.py +++ b/docs/models.py @@ -254,7 +254,7 @@ def breadcrumbs(self, document): else: return self.none() - def search(self, query_text, release): + def search(self, query_text, release, document_category=None): """Use full-text search to return documents matching query_text.""" query_text = query_text.strip() if query_text: @@ -268,9 +268,12 @@ def search(self, query_text, release): stop_sel=STOP_SEL, config=models.F("config"), ) + base_filter = Q(release_id=release.id) + if document_category: + base_filter &= Q(metadata__parents__startswith=document_category) base_qs = ( self.select_related("release__release") - .filter(release_id=release.id) + .filter(base_filter) .annotate( headline=search("title", search_query), highlight=search( diff --git a/docs/search.py b/docs/search.py index 06ce3a960..1a2ebcaa7 100644 --- a/docs/search.py +++ b/docs/search.py @@ -1,6 +1,7 @@ from django.contrib.postgres.search import SearchVector -from django.db.models import F +from django.db.models import F, TextChoices from django.db.models.fields.json import KeyTextTransform +from django.utils.translation import gettext_lazy as _ # Imported from # https://github.com/postgres/postgres/blob/REL_14_STABLE/src/bin/initdb/initdb.c#L659 @@ -51,3 +52,23 @@ START_SEL = "" STOP_SEL = "" + + +class DocumentationCategory(TextChoices): + """ + Categories used to filter the documentation search. + The value must match a folder name within django/docs. + """ + + # Diátaxis folders. + REFERENCE = "ref", _("API Reference") + TOPICS = "topics", _("Using Django") + HOWTO = "howto", _("How-to guides") + RELEASE_NOTES = "releases", _("Release notes") + + @classmethod + def parse(cls, value, default=None): + try: + return cls(value) + except ValueError: + return None diff --git a/docs/templates/docs/search_form.html b/docs/templates/docs/search_form.html index 7c44d75d6..65823c757 100644 --- a/docs/templates/docs/search_form.html +++ b/docs/templates/docs/search_form.html @@ -1,11 +1,12 @@ {% load i18n %} + +
+ + {{ form.q }} - - - {{ form.q }} - - -
+ + +
diff --git a/docs/templates/docs/search_results.html b/docs/templates/docs/search_results.html index f731ead75..4f400a838 100644 --- a/docs/templates/docs/search_results.html +++ b/docs/templates/docs/search_results.html @@ -1,7 +1,7 @@ {% extends "docs/doc.html" %} {% load i18n docs %} -{% block title %}{% trans "Search | Django documentation" %}{% endblock %} +{% block title %}{% translate "Search | Django documentation" %}{% endblock %} {% block toc-wrapper %}{% endblock %} {% block breadcrumbs-wrapper %}{% endblock %} @@ -11,23 +11,30 @@ {% block body %} {% if query %} + + {% translate "Filter the current search results by documentation category" %} + {% translate "All" context "all documentation categories" %} + {% for category in DocumentationCategory %} + {{ category.label }} + {% endfor %} +

{% if release.is_dev %} - {% blocktrans count num_results=paginator.count trimmed %} + {% blocktranslate count num_results=paginator.count trimmed %} Only 1 result for {{ query }} in the development version {% plural %} {{ num_results }} results for {{ query }} in the development version - {% endblocktrans %} + {% endblocktranslate %} {% else %} - {% blocktrans count num_results=paginator.count trimmed %} + {% blocktranslate count num_results=paginator.count trimmed %} Only 1 result for {{ query }} in version {{ version }} {% plural %} {{ num_results }} results for {{ query }} in version {{ version }} - {% endblocktrans %} + {% endblocktranslate %} {% endif %}

{% else %} -

{% trans "No search query given" %}

+

{% translate "No search query given" %}

{% endif %} {% if query %} @@ -64,6 +71,15 @@

{% endif %} + {% empty %} + {% if active_category %} +
+

+ {% querystring category=None page=None as all_search %} + {% blocktranslate trimmed %}Please try searching all documentation results.{% endblocktranslate %} +

+
+ {% endif %} {% endfor %} @@ -72,20 +88,20 @@