I need to implement a language-specific search in Wagtail, so I modified the default search/views.py
like this:
def search(request):
search_query = request.GET.get("query", None)
page = request.GET.get("page", 1)
language = request.LANGUAGE_CODE
if search_query:
search_results = Page.objects.live().filter(locale__language_code=language).search(search_query)
The result is an error message:
Please add index.FilterField('language_code') to Page.search_fields
Adding index.FilterField('language_code')
to my classes derived from Page
does not work – so how can I add that filter field index to wagtailcore.Page
?
You can also use Locale.get_active()
as a shortcut to get the current language. It's worth looking at defer_streamfields(), this will reduce the amount of data you're loading into memory also.
Page.objects.live().defer_streamfields().filter(locale=Locale.get_active()).search(search_query)
If you're using the Wagtail search backend, it only supports one SEARCH_CONFIG
even though you can add multiple in the settings. All that happens is each backend listed overwrites the previous and you end up with the last in the list. There is nothing in the wagtailsearch_indexentry
table that allows for different backends.
If you have the following:
WAGTAILSEARCH_BACKENDS = {
'default': {
'BACKEND': 'wagtail.search.backends.database',
'SEARCH_CONFIG': 'english_extended',
},
'es': {
'BACKEND': 'wagtail.search.backends.database',
'SEARCH_CONFIG': 'spanish',
},
'fr': {
'BACKEND': 'wagtail.search.backends.database',
'SEARCH_CONFIG': 'french',
},
}
In this case, the search backend will always be the French one, even if you specify the Spanish backend in your code with
from wagtail.search.backends import get_search_backend
s = get_search_backend('es')
scope = Page.objects.live().defer_streamfields().filter(locale=Locale.get_active())
search_results = s.search(search_query, scope)
s
will be using the French SEARCH_CONFIG
setting with French NLP (stemming and stop words) according to that dictionary instead.
Best solution I've come up with is to use the simple
dictionary and extend it with PostgrSQL unaccent support (adds full character set support for plain ascii, e.g. typing "hotel" will return results with "hôtel" etc.).
https://enzedonline.com/en/tech-blog/how-to-add-unaccent-support-in-postgresql-search/#6-test-stemming-with-unaccent
That disables the NLP, but at least makes it language neutral.
I raised this as an issue in 2022, but it never got any traction.