193 lines
5.8 KiB
Python
193 lines
5.8 KiB
Python
from typing import Any, Dict
|
|
|
|
from django.conf import settings
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.db.models.query import QuerySet
|
|
from django.http import Http404
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from wagtail.admin.forms.search import SearchForm
|
|
from wagtail.admin.ui.tables import Column, DateColumn
|
|
from wagtail.admin.ui.tables.pages import (
|
|
BulkActionsColumn,
|
|
NavigateToChildrenColumn,
|
|
PageStatusColumn,
|
|
PageTable,
|
|
PageTitleColumn,
|
|
ParentPageColumn,
|
|
)
|
|
from wagtail.admin.views.generic.base import BaseListingView
|
|
from wagtail.admin.views.generic.permissions import PermissionCheckedMixin
|
|
from wagtail.models import Page
|
|
from wagtail.permissions import page_permission_policy
|
|
from wagtail.search.query import MATCH_ALL
|
|
from wagtail.search.utils import parse_query_string
|
|
|
|
|
|
def page_filter_search(q, pages, all_pages=None, ordering=None):
|
|
# Parse query
|
|
filters, query = parse_query_string(q, operator="and", zero_terms=MATCH_ALL)
|
|
|
|
# Live filter
|
|
live_filter = filters.get("live") or filters.get("published")
|
|
live_filter = live_filter and live_filter.lower()
|
|
|
|
if live_filter in ["yes", "true"]:
|
|
if all_pages is not None:
|
|
all_pages = all_pages.filter(live=True)
|
|
pages = pages.filter(live=True)
|
|
elif live_filter in ["no", "false"]:
|
|
if all_pages is not None:
|
|
all_pages = all_pages.filter(live=False)
|
|
pages = pages.filter(live=False)
|
|
|
|
# Search
|
|
if all_pages is not None:
|
|
all_pages = all_pages.autocomplete(query, order_by_relevance=not ordering)
|
|
pages = pages.autocomplete(query, order_by_relevance=not ordering)
|
|
|
|
return pages, all_pages
|
|
|
|
|
|
class BaseSearchView(PermissionCheckedMixin, BaseListingView):
|
|
permission_policy = page_permission_policy
|
|
any_permission_required = {
|
|
"add",
|
|
"change",
|
|
"publish",
|
|
"bulk_delete",
|
|
"lock",
|
|
"unlock",
|
|
}
|
|
paginate_by = 20
|
|
page_kwarg = "p"
|
|
context_object_name = "pages"
|
|
table_class = PageTable
|
|
index_url_name = "wagtailadmin_pages:search"
|
|
|
|
columns = [
|
|
BulkActionsColumn("bulk_actions"),
|
|
PageTitleColumn(
|
|
"title",
|
|
classname="title",
|
|
label=_("Title"),
|
|
sort_key="title",
|
|
),
|
|
ParentPageColumn("parent", label=_("Parent")),
|
|
DateColumn(
|
|
"latest_revision_created_at",
|
|
label=_("Updated"),
|
|
sort_key="latest_revision_created_at",
|
|
width="12%",
|
|
),
|
|
Column(
|
|
"type",
|
|
label=_("Type"),
|
|
accessor="page_type_display_name",
|
|
width="12%",
|
|
),
|
|
PageStatusColumn(
|
|
"status",
|
|
label=_("Status"),
|
|
sort_key="live",
|
|
width="12%",
|
|
),
|
|
NavigateToChildrenColumn("navigate", width="10%"),
|
|
]
|
|
|
|
def get(self, request):
|
|
self.show_locale_labels = getattr(settings, "WAGTAIL_I18N_ENABLED", False)
|
|
self.content_types = []
|
|
self.ordering = None
|
|
|
|
if "ordering" in request.GET and request.GET["ordering"] in [
|
|
"title",
|
|
"-title",
|
|
"latest_revision_created_at",
|
|
"-latest_revision_created_at",
|
|
"live",
|
|
"-live",
|
|
]:
|
|
self.ordering = request.GET["ordering"]
|
|
|
|
if "content_type" in request.GET:
|
|
try:
|
|
app_label, model_name = request.GET["content_type"].split(".")
|
|
except ValueError:
|
|
raise Http404
|
|
|
|
try:
|
|
self.selected_content_type = ContentType.objects.get_by_natural_key(
|
|
app_label, model_name
|
|
)
|
|
except ContentType.DoesNotExist:
|
|
raise Http404
|
|
|
|
else:
|
|
self.selected_content_type = None
|
|
|
|
self.q = self.request.GET.get("q", "")
|
|
|
|
return super().get(request)
|
|
|
|
def get_queryset(self) -> QuerySet[Any]:
|
|
pages = self.all_pages = (
|
|
Page.objects.all().prefetch_related("content_type").specific()
|
|
)
|
|
if self.show_locale_labels:
|
|
pages = pages.select_related("locale")
|
|
|
|
if self.ordering:
|
|
pages = pages.order_by(self.ordering)
|
|
|
|
if self.selected_content_type:
|
|
pages = pages.filter(content_type=self.selected_content_type)
|
|
|
|
# Parse query and filter
|
|
pages, self.all_pages = page_filter_search(
|
|
self.q, pages, self.all_pages, self.ordering
|
|
)
|
|
|
|
# Facets
|
|
if pages.supports_facet:
|
|
self.content_types = [
|
|
(ContentType.objects.get(id=content_type_id), count)
|
|
for content_type_id, count in self.all_pages.facet(
|
|
"content_type_id"
|
|
).items()
|
|
]
|
|
|
|
return pages
|
|
|
|
def get_table_kwargs(self):
|
|
kwargs = super().get_table_kwargs()
|
|
kwargs["show_locale_labels"] = self.show_locale_labels
|
|
kwargs["actions_next_url"] = self.get_index_url()
|
|
return kwargs
|
|
|
|
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
|
context = super().get_context_data(**kwargs)
|
|
context.update(
|
|
{
|
|
"all_pages": self.all_pages,
|
|
"query_string": self.q,
|
|
"content_types": self.content_types,
|
|
"selected_content_type": self.selected_content_type,
|
|
"ordering": self.ordering,
|
|
}
|
|
)
|
|
return context
|
|
|
|
|
|
class SearchView(BaseSearchView):
|
|
template_name = "wagtailadmin/pages/search.html"
|
|
|
|
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
|
context = super().get_context_data(**kwargs)
|
|
context["search_form"] = SearchForm(self.request.GET)
|
|
return context
|
|
|
|
|
|
class SearchResultsView(BaseSearchView):
|
|
template_name = "wagtailadmin/pages/search_results.html"
|