From 72db917ddcc3691539916ab88c692c8c7225f70b Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 27 May 2015 16:31:21 +0100 Subject: [PATCH 1/5] Add AUTO_UPDATE option to backend parameters By default, Wagtail will keep all search indexes up to date using signal handlers. This is sometimes not needed/wanted. This PR allows auto-update to be configured on a per-index basis. --- wagtail/wagtailsearch/backends/__init__.py | 7 +++++-- wagtail/wagtailsearch/signal_handlers.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailsearch/backends/__init__.py b/wagtail/wagtailsearch/backends/__init__.py index fa6fcf017f..3877677ad8 100644 --- a/wagtail/wagtailsearch/backends/__init__.py +++ b/wagtail/wagtailsearch/backends/__init__.py @@ -51,9 +51,12 @@ def get_search_backend(backend='default', **kwargs): return backend_cls(params) -def get_search_backends(): +def get_search_backends(with_auto_update=False): if hasattr(settings, 'WAGTAILSEARCH_BACKENDS'): - for backend in settings.WAGTAILSEARCH_BACKENDS.keys(): + for backend, params in settings.WAGTAILSEARCH_BACKENDS.items(): + if with_auto_update and params.get('AUTO_UPDATE', True) is False: + continue + yield get_search_backend(backend) else: yield get_search_backend('default') diff --git a/wagtail/wagtailsearch/signal_handlers.py b/wagtail/wagtailsearch/signal_handlers.py index 6f701af31b..395e599677 100644 --- a/wagtail/wagtailsearch/signal_handlers.py +++ b/wagtail/wagtailsearch/signal_handlers.py @@ -20,7 +20,7 @@ def post_save_signal_handler(instance, **kwargs): indexed_instance = get_indexed_instance(instance) if indexed_instance: - for backend in get_search_backends(): + for backend in get_search_backends(with_auto_update=True): backend.add(indexed_instance) @@ -28,7 +28,7 @@ def post_delete_signal_handler(instance, **kwargs): indexed_instance = get_indexed_instance(instance) if indexed_instance: - for backend in get_search_backends(): + for backend in get_search_backends(with_auto_update=True): backend.delete(indexed_instance) From c837afdfa23cec911d06f0bc1c9dbb85d3ccaa77 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 27 May 2015 16:36:18 +0100 Subject: [PATCH 2/5] Disabled AUTO_UPDATE on Elasticsearch backend in tests --- wagtail/tests/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index c5e06592a8..88f7eb2350 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -150,6 +150,7 @@ try: 'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch', 'TIMEOUT': 10, 'max_retries': 1, + 'AUTO_UPDATE': False, } if 'ELASTICSEARCH_URL' in os.environ: From e7c61b13b14fb22e50b757d39a587a885908f193 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 29 May 2015 11:04:54 +0100 Subject: [PATCH 3/5] Improve docs for WAGTAILSEARCH_BACKENDS setting Including docs for new AUTO_UPDATE parameter --- docs/topics/search/backends.rst | 40 +++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/topics/search/backends.rst b/docs/topics/search/backends.rst index 24d19ab0cf..c19da48b57 100644 --- a/docs/topics/search/backends.rst +++ b/docs/topics/search/backends.rst @@ -7,13 +7,45 @@ Backends Wagtailsearch has support for multiple backends giving you the choice between using the database for search or an external service such as Elasticsearch. -You can configure which backend to use with the ``WAGTAILSEARCH_BACKENDS`` setting. +You can configure which backend to use with the ``WAGTAILSEARCH_BACKENDS`` setting: +.. code-block:: python + + WAGTAILSEARCH_BACKENDS = { + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch', + } + } + + +``AUTO_UPDATE`` +=============== + +By default, Wagtail will automatically keep all indexes up to date. This could impact performance when editing content, especially if your index is hosted on an external service. + +The ``AUTO_UPDATE`` setting allows you to disable this on a per-index basis: + +.. code-block:: python + + WAGTAILSEARCH_BACKENDS = { + 'default': { + 'BACKEND': ..., + 'AUTO_UPDATE': False, + } + } + +If you have disabled auto update, you must run the :ref:`update_index` command on a regular basis to keep the index in sync with the database. + + +``BACKEND`` +=========== + +Here's a list of backends that Wagtail supports out of the box. .. _wagtailsearch_backends_database: Database Backend (default) -========================== +-------------------------- ``wagtail.wagtailsearch.backends.db.DBSearch`` @@ -29,7 +61,7 @@ If any of these features are important to you, we recommend using Elasticsearch Elasticsearch Backend -===================== +--------------------- ``wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch`` @@ -71,6 +103,6 @@ If you prefer not to run an Elasticsearch server in development or production, t Rolling Your Own -================ +---------------- Wagtail search backends implement the interface defined in ``wagtail/wagtail/wagtailsearch/backends/base.py``. At a minimum, the backend's ``search()`` method must return a collection of objects or ``model.objects.none()``. For a fully-featured search backend, examine the Elasticsearch backend code in ``elasticsearch.py``. From 1e0a203f86cc2c629748fe3d8527625096648ce2 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 29 May 2015 13:59:16 +0100 Subject: [PATCH 4/5] Added tests for get_search_backends --- wagtail/wagtailsearch/tests/test_backends.py | 63 ++++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailsearch/tests/test_backends.py b/wagtail/wagtailsearch/tests/test_backends.py index ef22ae3c06..9a50d9c42a 100644 --- a/wagtail/wagtailsearch/tests/test_backends.py +++ b/wagtail/wagtailsearch/tests/test_backends.py @@ -9,7 +9,7 @@ from django.core import management from wagtail.tests.utils import WagtailTestUtils from wagtail.tests.search import models -from wagtail.wagtailsearch.backends import get_search_backend, InvalidSearchBackendError +from wagtail.wagtailsearch.backends import get_search_backend, get_search_backends, InvalidSearchBackendError from wagtail.wagtailsearch.backends.db import DBSearch @@ -132,9 +132,11 @@ class BackendTests(WagtailTestUtils): self.assertEqual(set(results), {self.testa, self.testb, self.testc.searchtest_ptr, self.testd.searchtest_ptr}) -@override_settings(WAGTAILSEARCH_BACKENDS={ - 'default': {'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch'} -}) +@override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': {'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch'} + } +) class TestBackendLoader(TestCase): def test_import_by_name(self): db = get_search_backend(backend='default') @@ -149,3 +151,56 @@ class TestBackendLoader(TestCase): def test_invalid_backend_import(self): self.assertRaises(InvalidSearchBackendError, get_search_backend, backend="I'm not a backend!") + + def test_get_search_backends(self): + backends = list(get_search_backends()) + + self.assertEqual(len(backends), 1) + self.assertIsInstance(backends[0], DBSearch) + + @override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch' + }, + 'another-backend': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch' + }, + } + ) + def test_get_search_backends_multiple(self): + backends = list(get_search_backends()) + + self.assertEqual(len(backends), 2) + + def test_get_search_backends_with_auto_update(self): + backends = list(get_search_backends(with_auto_update=True)) + + # Auto update is the default + self.assertEqual(len(backends), 1) + + @override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch', + 'AUTO_UPDATE': False, + }, + } + ) + def test_get_search_backends_with_auto_update_disabled(self): + backends = list(get_search_backends(with_auto_update=True)) + + self.assertEqual(len(backends), 0) + + @override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch', + 'AUTO_UPDATE': False, + }, + } + ) + def test_get_search_backends_without_auto_update_disabled(self): + backends = list(get_search_backends()) + + self.assertEqual(len(backends), 1) From e2a44fe0a5eecc6bc38c89ad06cfcc24417e2adf Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 29 May 2015 16:24:23 +0100 Subject: [PATCH 5/5] release note for #1349 --- CHANGELOG.txt | 1 + docs/releases/1.0.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 182a5c0c26..f8d5a4eb8f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -53,6 +53,7 @@ Changelog * Added a new decorator-based syntax for RoutablePage, compatible with Django 1.8 * Collapsible blocks stay open on any form error (Salvador Faria) * Document upload modal no longer switches tabs on form errors (Salvador Faria) + * Added `AUTO_UPDATE` flag to search backend settings to enable/disable automatically updating the search index on model changes 0.8.8 (xx.xx.2015) diff --git a/docs/releases/1.0.rst b/docs/releases/1.0.rst index fab9cbd723..3a8ac40eb1 100644 --- a/docs/releases/1.0.rst +++ b/docs/releases/1.0.rst @@ -119,6 +119,7 @@ Search ------ * Search view accepts "page" GET parameter in line with pagination + * Added ``AUTO_UPDATE`` flag to search backend settings to enable/disable automatically updating the search index on model changes Routable pages