Skip to content

Instantly share code, notes, and snippets.

@cnk
Created May 4, 2022 15:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cnk/27bfc40ddf8d33f33defac57cd840e4a to your computer and use it in GitHub Desktop.
Save cnk/27bfc40ddf8d33f33defac57cd840e4a to your computer and use it in GitHub Desktop.
Site-specific search for wagtail 2.16
#################################################################################################################
# Patch the wagtail.admin.views.pages.search.search method to filter by the current site.
# I asked Torchbox to add a hook that would let us delete this patch: https://github.com/wagtail/wagtail/issues/6235
# 2020-09-03 cnk: updated to work with 2.11a
#################################################################################################################
@vary_on_headers('X-Requested-With')
@user_passes_test(user_has_any_page_permission)
def single_site_search(request):
# BEGIN PATCH
pages = all_pages = Page.objects.in_site(Site.find_for_request(request)).prefetch_related('content_type').specific()
# END PATCH
q = MATCH_ALL
content_types = []
pagination_query_params = QueryDict({}, mutable=True)
ordering = None
if 'ordering' in request.GET:
if request.GET['ordering'] in [
'title', '-title', 'latest_revision_created_at', '-latest_revision_created_at', 'live', '-live'
]:
ordering = request.GET['ordering']
if ordering == 'title':
pages = pages.order_by('title')
elif ordering == '-title':
pages = pages.order_by('-title')
if ordering == 'latest_revision_created_at':
pages = pages.order_by('latest_revision_created_at')
elif ordering == '-latest_revision_created_at':
pages = pages.order_by('-latest_revision_created_at')
if ordering == 'live':
pages = pages.order_by('live')
elif ordering == '-live':
pages = pages.order_by('-live')
if 'content_type' in request.GET:
pagination_query_params['content_type'] = request.GET['content_type']
app_label, model_name = request.GET['content_type'].split('.')
try:
selected_content_type = ContentType.objects.get_by_natural_key(app_label, model_name)
except ContentType.DoesNotExist:
raise Http404
pages = pages.filter(content_type=selected_content_type)
else:
selected_content_type = None
if 'q' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
q = form.cleaned_data['q']
pagination_query_params['q'] = q
# 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']:
all_pages = all_pages.filter(live=True)
pages = pages.filter(live=True)
elif live_filter in ['no', 'false']:
all_pages = all_pages.filter(live=False)
pages = pages.filter(live=False)
# Search
all_pages = all_pages.search(query, order_by_relevance=not ordering)
pages = pages.search(query, order_by_relevance=not ordering)
# Facets
if pages.supports_facet:
content_types = [
(ContentType.objects.get(id=content_type_id), count)
for content_type_id, count in all_pages.facet('content_type_id').items()
]
else:
form = SearchForm()
paginator = Paginator(pages, per_page=20)
pages = paginator.get_page(request.GET.get('p'))
# https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpRequest.is_ajax
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
return TemplateResponse(request, "wagtailadmin/pages/search_results.html", {
'pages': pages,
'all_pages': all_pages,
'query_string': q,
'content_types': content_types,
'selected_content_type': selected_content_type,
'ordering': ordering,
'pagination_query_params': pagination_query_params.urlencode(),
})
else:
return TemplateResponse(request, "wagtailadmin/pages/search.html", {
'search_form': form,
'pages': pages,
'all_pages': all_pages,
'query_string': q,
'content_types': content_types,
'selected_content_type': selected_content_type,
'ordering': ordering,
'pagination_query_params': pagination_query_params.urlencode(),
})
wagtail.admin.views.pages.search.search = single_site_search
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment