Allow search backends to be imported by module

This allows the elasticsearch backend to be imported like "wagtail.wagtailsearch.backends.elasticsearch" (dropping .ElasticSearch from the end of the import string)
This commit is contained in:
Karl Hobley 2015-04-30 12:36:24 +01:00
parent bbdb4379a0
commit d94cde879c
9 changed files with 48 additions and 12 deletions

View file

@ -162,7 +162,7 @@ Search
# Replace the search backend
WAGTAILSEARCH_BACKENDS = {
'default': {
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch',
'INDEX': 'myapp'
}
}
@ -498,7 +498,7 @@ These two files should reside in your project directory (``myproject/myproject/`
# Replace the search backend
#WAGTAILSEARCH_BACKENDS = {
# 'default': {
# 'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
# 'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch',
# 'INDEX': 'myapp'
# }
#}

View file

@ -34,7 +34,7 @@ The backend is configured in settings:
WAGTAILSEARCH_BACKENDS = {
'default': {
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch',
'URLS': ['http://localhost:9200'],
'INDEX': 'wagtail',
'TIMEOUT': 5,

View file

@ -135,7 +135,7 @@ COMPRESS_ENABLED = False # disable compression so that we can run tests on the
WAGTAILSEARCH_BACKENDS = {
'default': {
'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch',
'BACKEND': 'wagtail.wagtailsearch.backends.db',
}
}
@ -147,7 +147,7 @@ try:
# Import succeeded, add an Elasticsearch backend
WAGTAILSEARCH_BACKENDS['elasticsearch'] = {
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch',
'TIMEOUT': 10,
'max_retries': 1,
}

View file

@ -2,6 +2,9 @@
# Based on the Django cache framework
# https://github.com/django/django/blob/5d263dee304fdaf95e18d2f0619d6925984a7f02/django/core/cache/__init__.py
import sys
import six
from importlib import import_module
from django.utils.module_loading import import_string
from django.core.exceptions import ImproperlyConfigured
@ -12,11 +15,34 @@ class InvalidSearchBackendError(ImproperlyConfigured):
pass
def import_backend(dotted_path):
"""
Theres two formats for the dotted_path.
One with the backend class (old) and one without (new)
eg:
old: wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch
new: wagtail.wagtailsearch.backends.elasticsearch
If a new style dotted path was specified, this function would
look for a backend class from the "SearchBackend" attribute.
"""
try:
# New
backend_module = import_module(dotted_path)
return backend_module.SearchBackend
except ImportError as e:
try:
# Old
return import_string(dotted_path)
except ImportError:
six.reraise(ImportError, e, sys.exc_info()[2])
def get_search_backend(backend='default', **kwargs):
# Get configuration
default_conf = {
'default': {
'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch',
'BACKEND': 'wagtail.wagtailsearch.backends.db',
},
}
WAGTAILSEARCH_BACKENDS = getattr(
@ -29,7 +55,7 @@ def get_search_backend(backend='default', **kwargs):
except KeyError:
try:
# Trying to import the given backend, in case it's a dotted path
import_string(backend)
import_backend(backend)
except ImportError as e:
raise InvalidSearchBackendError("Could not find backend '%s': %s" % (
backend, e))
@ -42,7 +68,7 @@ def get_search_backend(backend='default', **kwargs):
# Try to import the backend
try:
backend_cls = import_string(backend)
backend_cls = import_backend(backend)
except ImportError as e:
raise InvalidSearchBackendError("Could not find backend '%s': %s" % (
backend, e))

View file

@ -93,3 +93,6 @@ class DBSearch(BaseSearch):
def _search(self, queryset, query_string, fields=None):
return DBSearchResults(self, DBSearchQuery(queryset, query_string, fields=fields))
SearchBackend = DBSearch

View file

@ -465,3 +465,6 @@ class ElasticSearch(BaseSearch):
def _search(self, queryset, query_string, fields=None):
return ElasticSearchResults(self, ElasticSearchQuery(queryset, query_string, fields=fields))
SearchBackend = ElasticSearch

View file

@ -133,7 +133,7 @@ class BackendTests(WagtailTestUtils):
@override_settings(WAGTAILSEARCH_BACKENDS={
'default': {'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch'}
'default': {'BACKEND': 'wagtail.wagtailsearch.backends.db'}
})
class TestBackendLoader(TestCase):
def test_import_by_name(self):
@ -141,11 +141,15 @@ class TestBackendLoader(TestCase):
self.assertIsInstance(db, DBSearch)
def test_import_by_path(self):
db = get_search_backend(backend='wagtail.wagtailsearch.backends.db')
self.assertIsInstance(db, DBSearch)
def test_import_by_full_path(self):
db = get_search_backend(backend='wagtail.wagtailsearch.backends.db.DBSearch')
self.assertIsInstance(db, DBSearch)
def test_nonexistent_backend_import(self):
self.assertRaises(InvalidSearchBackendError, get_search_backend, backend='wagtail.wagtailsearch.backends.doesntexist.DoesntExist')
self.assertRaises(InvalidSearchBackendError, get_search_backend, backend='wagtail.wagtailsearch.backends.doesntexist')
def test_invalid_backend_import(self):
self.assertRaises(InvalidSearchBackendError, get_search_backend, backend="I'm not a backend!")

View file

@ -6,7 +6,7 @@ from .test_backends import BackendTests
class TestDBBackend(BackendTests, TestCase):
backend_path = 'wagtail.wagtailsearch.backends.db.DBSearch'
backend_path = 'wagtail.wagtailsearch.backends.db'
@unittest.expectedFailure
def test_callable_indexed_field(self):

View file

@ -13,7 +13,7 @@ from .test_backends import BackendTests
class TestElasticSearchBackend(BackendTests, TestCase):
backend_path = 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch'
backend_path = 'wagtail.wagtailsearch.backends.elasticsearch'
def test_search_with_spaces_only(self):
# Search for some space characters and hope it doesn't crash