I'm creating a blog site for a friend and there are certain page models that I would like to be excluded from users' searches. These models are BlogIndexPage
and ThankYouPage
. Both of these models subclass wagtail.models.Page
. I want to have control over how these pages are visited and therefore don't want links for them to show up in search results if users search—for example—thank or blog.
For context, this is the search
view function:
def search(request):
search_query = request.GET.get("query", None)
page = request.GET.get("page", 1)
# Search
if search_query:
search_results = (
Page.objects.live().order_by("-first_published_at").search(search_query)
)
query = Query.get(search_query)
# Record hit
query.add_hit()
else:
search_results = Page.objects.none()
# etc...
I've tried the two solutions suggested in this other thread and a third solution I found in the documentation, but they did not solve my problem. Specifically I tried the following:
class ThankYouPage(Page):
...
# Method One:
@classmethod
def get_indexed_objects(cls):
return cls.objects.none()
# Method Two:
def get_indexed_instance(self):
return None
# Method Three:
search_fields = []
I ran the update_index
management command after each change.
In the Django shell, I get the following behavior:
>>> from wagtail.models import Page
>>> from apps.contact.models import ThankYouPage
>>>
>>> Page.objects.all().search("thank")
<SearchResults [<Page: Thank You Page>]>
>>>
>>> ThankYouPage.objects.all().search("thank")
<SearchResults []>
>>>
The issue seems to be that the .search()
method returns a list-like object of Page
instances instead of specific subclass instances. I can solve this issue by adding an .exclude()
method to the search queryset:
excluded_page_ids = [
4, # BlogIndexPage
26, # ThankYouPage
]
def search(request):
search_query = request.GET.get("query", None)
page = request.GET.get("page", 1)
# Search
if search_query:
search_results = (
Page.objects.live()
.exclude(id__in=excluded_page_ids) # Manually exclude certain pages
.order_by("-first_published_at")
.search(search_query)
)
query = Query.get(search_query)
# Record hit
query.add_hit()
else:
search_results = Page.objects.none()
# etc...
But this feels like an unsustainable bad practice. Is there a more pythonic or wagtailian way of doing this?