1

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?

James
  • 11
  • 2

1 Answers1

0

Set search_fields =[] in the page subclasses you do not want in search results. https://docs.wagtail.org/en/latest/topics/search/indexing.html#disabling-model-indexing

cnk
  • 981
  • 1
  • 5
  • 9
  • I included that exact same link in my post along with an explanation that I already tried doing that. Is there something I need to do in addition to that? It doesn't seem to work by itself. – James Aug 01 '23 at 17:09
  • Sorry, I missed that. What version of Wagtail are you using and which search backend? – cnk Aug 02 '23 at 03:06
  • No worries! I'm sure I wrote more than I needed to for this question. Wagtail version is 5.0.1 and the search backend is just the database's full text search (sqlite for dev, MySQL for production). – James Aug 02 '23 at 13:03