Merge pull request #562 from kaedroho/indexed-rename

Renamed wagtailsearch.indexed to wagtailsearch.index
pull/572/head
Karl Hobley 2014-08-26 12:09:08 +01:00
commit d9dc42dee6
15 zmienionych plików z 231 dodań i 218 usunięć

Wyświetl plik

@ -17,7 +17,7 @@ from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel
from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField
from wagtail.wagtailsnippets.models import register_snippet
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch import index
from wagtail.contrib.wagtailroutablepage.models import RoutablePage
@ -387,19 +387,19 @@ class BusinessChild(Page):
subpage_types = []
class SearchTest(models.Model, indexed.Indexed):
class SearchTest(models.Model, index.Indexed):
title = models.CharField(max_length=255)
content = models.TextField()
live = models.BooleanField(default=False)
published_date = models.DateField(null=True)
search_fields = [
indexed.SearchField('title', partial_match=True),
indexed.SearchField('content'),
indexed.SearchField('callable_indexed_field'),
indexed.FilterField('title'),
indexed.FilterField('live'),
indexed.FilterField('published_date'),
index.SearchField('title', partial_match=True),
index.SearchField('content'),
index.SearchField('callable_indexed_field'),
index.FilterField('title'),
index.FilterField('live'),
index.FilterField('published_date'),
]
def callable_indexed_field(self):
@ -411,12 +411,12 @@ class SearchTestChild(SearchTest):
extra_content = models.TextField()
search_fields = SearchTest.search_fields + [
indexed.SearchField('subtitle', partial_match=True),
indexed.SearchField('extra_content'),
index.SearchField('subtitle', partial_match=True),
index.SearchField('extra_content'),
]
class SearchTestOldConfig(models.Model, indexed.Indexed):
class SearchTestOldConfig(models.Model, index.Indexed):
"""
This tests that the Indexed class can correctly handle models that
use the old "indexed_fields" configuration format.
@ -437,7 +437,7 @@ class SearchTestOldConfig(models.Model, indexed.Indexed):
}
class SearchTestOldConfigList(models.Model, indexed.Indexed):
class SearchTestOldConfigList(models.Model, index.Indexed):
"""
This tests that the Indexed class can correctly handle models that
use the old "indexed_fields" configuration format using a list.

Wyświetl plik

@ -4,3 +4,7 @@ class RemovedInWagtail06Warning(DeprecationWarning):
class RemovedInWagtail07Warning(PendingDeprecationWarning):
pass
class RemovedInWagtail08Warning(PendingDeprecationWarning):
pass

Wyświetl plik

@ -4,19 +4,19 @@ from django.contrib.contenttypes.models import ContentType
from django.db.models import Count
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch import index
from wagtail.wagtailsearch.backends import get_search_backend
class TagSearchable(indexed.Indexed):
class TagSearchable(index.Indexed):
"""
Mixin to provide a 'search' method, searching on the 'title' field and tags,
for models that provide those things.
"""
search_fields = (
indexed.SearchField('title', partial_match=True, boost=10),
indexed.SearchField('get_tags', partial_match=True, boost=10)
index.SearchField('title', partial_match=True, boost=10),
index.SearchField('get_tags', partial_match=True, boost=10)
)
@property

Wyświetl plik

@ -32,7 +32,7 @@ from wagtail.wagtailcore.utils import camelcase_to_underscore
from wagtail.wagtailcore.query import PageQuerySet
from wagtail.wagtailcore.url_routing import RouteResult
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch import index
from wagtail.wagtailsearch.backends import get_search_backend
@ -274,7 +274,7 @@ class PageBase(models.base.ModelBase):
@python_2_unicode_compatible
class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, indexed.Indexed)):
class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed)):
title = models.CharField(max_length=255, help_text=_("The page title as you'd like it to be seen by the public"))
slug = models.SlugField(help_text=_("The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/"))
# TODO: enforce uniqueness on slug field per parent (will have to be done at the Django
@ -294,13 +294,13 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, indexed.Index
expired = models.BooleanField(default=False, editable=False)
search_fields = (
indexed.SearchField('title', partial_match=True, boost=100),
indexed.FilterField('id'),
indexed.FilterField('live'),
indexed.FilterField('owner'),
indexed.FilterField('content_type'),
indexed.FilterField('path'),
indexed.FilterField('depth'),
index.SearchField('title', partial_match=True, boost=100),
index.FilterField('id'),
index.FilterField('live'),
index.FilterField('owner'),
index.FilterField('content_type'),
index.FilterField('path'),
index.FilterField('depth'),
)
def __init__(self, *args, **kwargs):

Wyświetl plik

@ -13,7 +13,7 @@ from django.utils.encoding import python_2_unicode_compatible
from wagtail.wagtailadmin.taggable import TagSearchable
from wagtail.wagtailadmin.utils import get_object_usage
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch import index
@python_2_unicode_compatible
@ -26,7 +26,7 @@ class Document(models.Model, TagSearchable):
tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))
search_fields = TagSearchable.search_fields + (
indexed.FilterField('uploaded_by_user'),
index.FilterField('uploaded_by_user'),
)
def __str__(self):

Wyświetl plik

@ -22,7 +22,7 @@ from unidecode import unidecode
from wagtail.wagtailadmin.taggable import TagSearchable
from wagtail.wagtailimages.backends import get_image_backend
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch import index
from wagtail.wagtailimages.utils.validators import validate_image_format
from wagtail.wagtailimages.utils.focal_point import FocalPoint
from wagtail.wagtailimages.utils.feature_detection import FeatureDetector, opencv_available
@ -68,7 +68,7 @@ class AbstractImage(models.Model, TagSearchable):
args=(self.id,))
search_fields = TagSearchable.search_fields + (
indexed.FilterField('uploaded_by_user'),
index.FilterField('uploaded_by_user'),
)
def __str__(self):

Wyświetl plik

@ -1,3 +1,3 @@
from wagtail.wagtailsearch.indexed import Indexed
from wagtail.wagtailsearch.index import Indexed
from wagtail.wagtailsearch.signal_handlers import register_signal_handlers
from wagtail.wagtailsearch.backends import get_search_backend

Wyświetl plik

@ -2,7 +2,7 @@ from django.db import models
from django.db.models.query import QuerySet
from django.core.exceptions import ImproperlyConfigured
from wagtail.wagtailsearch.indexed import Indexed
from wagtail.wagtailsearch.index import Indexed
from wagtail.wagtailsearch.utils import normalise_query_string

Wyświetl plik

@ -1,7 +1,6 @@
from django.db import models
from wagtail.wagtailsearch.backends.base import BaseSearch
from wagtail.wagtailsearch.indexed import Indexed
class DBSearch(BaseSearch):

Wyświetl plik

@ -11,7 +11,7 @@ from elasticsearch import Elasticsearch, NotFoundError, RequestError
from elasticsearch.helpers import bulk
from wagtail.wagtailsearch.backends.base import BaseSearch
from wagtail.wagtailsearch.indexed import Indexed, SearchField, FilterField
from wagtail.wagtailsearch.index import Indexed, SearchField, FilterField
class ElasticSearchMapping(object):

Wyświetl plik

@ -0,0 +1,182 @@
import warnings
from six import string_types
from django.db import models
from wagtail.utils.deprecation import RemovedInWagtail06Warning
class Indexed(object):
@classmethod
def indexed_get_parent(cls, require_model=True):
for base in cls.__bases__:
if issubclass(base, Indexed) and (issubclass(base, models.Model) or require_model is False):
return base
@classmethod
def indexed_get_content_type(cls):
# Work out content type
content_type = (cls._meta.app_label + '_' + cls.__name__).lower()
# Get parent content type
parent = cls.indexed_get_parent()
if parent:
parent_content_type = parent.indexed_get_content_type()
return parent_content_type + '_' + content_type
else:
return content_type
@classmethod
def indexed_get_toplevel_content_type(cls):
# Get parent content type
parent = cls.indexed_get_parent()
if parent:
return parent.indexed_get_content_type()
else:
# At toplevel, return this content type
return (cls._meta.app_label + '_' + cls.__name__).lower()
@classmethod
def indexed_get_indexed_fields(cls):
# Get indexed fields for this class as dictionary
indexed_fields = cls.indexed_fields
if isinstance(indexed_fields, dict):
# Make sure we have a copy to prevent us accidentally changing the configuration
indexed_fields = indexed_fields.copy()
else:
# Convert to dict
if isinstance(indexed_fields, tuple):
indexed_fields = list(indexed_fields)
if isinstance(indexed_fields, string_types):
indexed_fields = [indexed_fields]
if isinstance(indexed_fields, list):
indexed_fields = dict((field, dict(type='string')) for field in indexed_fields)
if not isinstance(indexed_fields, dict):
raise ValueError()
# Get indexed fields for parent class
parent = cls.indexed_get_parent(require_model=False)
if parent:
# Add parent fields into this list
parent_indexed_fields = parent.indexed_get_indexed_fields().copy()
parent_indexed_fields.update(indexed_fields)
indexed_fields = parent_indexed_fields
return indexed_fields
@classmethod
def get_search_fields(cls):
search_fields = []
if hasattr(cls, 'search_fields'):
search_fields.extend(cls.search_fields)
# Backwards compatibility with old indexed_fields setting
# Get indexed fields
indexed_fields = cls.indexed_get_indexed_fields()
# Display deprecation warning if indexed_fields has been used
if indexed_fields:
warnings.warn("'indexed_fields' setting is now deprecated."
"Use 'search_fields' instead.", RemovedInWagtail06Warning)
# Convert them into search fields
for field_name, _config in indexed_fields.items():
# Copy the config to prevent is trashing anything accidentally
config = _config.copy()
# Check if this is a filter field
if config.get('index', None) == 'not_analyzed':
config.pop('index')
search_fields.append(FilterField(field_name, es_extra=config))
continue
# Must be a search field, check for boosting and partial matching
boost = config.pop('boost', None)
partial_match = False
if config.get('analyzer', None) == 'edgengram_analyzer':
partial_match = True
config.pop('analyzer')
# Add the field
search_fields.append(SearchField(field_name, boost=boost, partial_match=partial_match, es_extra=config))
# Remove any duplicate entries into search fields
# We need to take into account that fields can be indexed as both a SearchField and as a FilterField
search_fields_dict = {}
for field in search_fields:
search_fields_dict[(field.field_name, type(field))] = field
search_fields = search_fields_dict.values()
return search_fields
@classmethod
def get_searchable_search_fields(cls):
return filter(lambda field: isinstance(field, SearchField), cls.get_search_fields())
@classmethod
def get_filterable_search_fields(cls):
return filter(lambda field: isinstance(field, FilterField), cls.get_search_fields())
@classmethod
def get_indexed_objects(cls):
return cls.objects.all()
indexed_fields = ()
class BaseField(object):
suffix = ''
def __init__(self, field_name, **kwargs):
self.field_name = field_name
self.kwargs = kwargs
def get_field(self, cls):
return cls._meta.get_field_by_name(self.field_name)[0]
def get_attname(self, cls):
try:
field = self.get_field(cls)
return field.attname
except models.fields.FieldDoesNotExist:
return self.field_name
def get_index_name(self, cls):
return self.get_attname(cls) + self.suffix
def get_type(self, cls):
if 'type' in self.kwargs:
return self.kwargs['type']
try:
field = self.get_field(cls)
return field.get_internal_type()
except models.fields.FieldDoesNotExist:
return 'CharField'
def get_value(self, obj):
try:
field = self.get_field(obj.__class__)
return field._get_val_from_obj(obj)
except models.fields.FieldDoesNotExist:
value = getattr(obj, self.field_name, None)
if hasattr(value, '__call__'):
value = value()
return value
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.field_name)
class SearchField(BaseField):
def __init__(self, field_name, boost=None, partial_match=False, **kwargs):
super(SearchField, self).__init__(field_name, **kwargs)
self.boost = boost
self.partial_match = partial_match
class FilterField(BaseField):
suffix = '_filter'

Wyświetl plik

@ -1,182 +1,11 @@
import warnings
from six import string_types
from django.db import models
from wagtail.utils.deprecation import RemovedInWagtail06Warning
from wagtail.utils.deprecation import RemovedInWagtail08Warning
class Indexed(object):
@classmethod
def indexed_get_parent(cls, require_model=True):
for base in cls.__bases__:
if issubclass(base, Indexed) and (issubclass(base, models.Model) or require_model is False):
return base
@classmethod
def indexed_get_content_type(cls):
# Work out content type
content_type = (cls._meta.app_label + '_' + cls.__name__).lower()
# Get parent content type
parent = cls.indexed_get_parent()
if parent:
parent_content_type = parent.indexed_get_content_type()
return parent_content_type + '_' + content_type
else:
return content_type
@classmethod
def indexed_get_toplevel_content_type(cls):
# Get parent content type
parent = cls.indexed_get_parent()
if parent:
return parent.indexed_get_content_type()
else:
# At toplevel, return this content type
return (cls._meta.app_label + '_' + cls.__name__).lower()
@classmethod
def indexed_get_indexed_fields(cls):
# Get indexed fields for this class as dictionary
indexed_fields = cls.indexed_fields
if isinstance(indexed_fields, dict):
# Make sure we have a copy to prevent us accidentally changing the configuration
indexed_fields = indexed_fields.copy()
else:
# Convert to dict
if isinstance(indexed_fields, tuple):
indexed_fields = list(indexed_fields)
if isinstance(indexed_fields, string_types):
indexed_fields = [indexed_fields]
if isinstance(indexed_fields, list):
indexed_fields = dict((field, dict(type='string')) for field in indexed_fields)
if not isinstance(indexed_fields, dict):
raise ValueError()
# Get indexed fields for parent class
parent = cls.indexed_get_parent(require_model=False)
if parent:
# Add parent fields into this list
parent_indexed_fields = parent.indexed_get_indexed_fields().copy()
parent_indexed_fields.update(indexed_fields)
indexed_fields = parent_indexed_fields
return indexed_fields
@classmethod
def get_search_fields(cls):
search_fields = []
if hasattr(cls, 'search_fields'):
search_fields.extend(cls.search_fields)
# Backwards compatibility with old indexed_fields setting
# Get indexed fields
indexed_fields = cls.indexed_get_indexed_fields()
# Display deprecation warning if indexed_fields has been used
if indexed_fields:
warnings.warn("'indexed_fields' setting is now deprecated."
"Use 'search_fields' instead.", RemovedInWagtail06Warning)
# Convert them into search fields
for field_name, _config in indexed_fields.items():
# Copy the config to prevent is trashing anything accidentally
config = _config.copy()
# Check if this is a filter field
if config.get('index', None) == 'not_analyzed':
config.pop('index')
search_fields.append(FilterField(field_name, es_extra=config))
continue
# Must be a search field, check for boosting and partial matching
boost = config.pop('boost', None)
partial_match = False
if config.get('analyzer', None) == 'edgengram_analyzer':
partial_match = True
config.pop('analyzer')
# Add the field
search_fields.append(SearchField(field_name, boost=boost, partial_match=partial_match, es_extra=config))
# Remove any duplicate entries into search fields
# We need to take into account that fields can be indexed as both a SearchField and as a FilterField
search_fields_dict = {}
for field in search_fields:
search_fields_dict[(field.field_name, type(field))] = field
search_fields = search_fields_dict.values()
return search_fields
@classmethod
def get_searchable_search_fields(cls):
return filter(lambda field: isinstance(field, SearchField), cls.get_search_fields())
@classmethod
def get_filterable_search_fields(cls):
return filter(lambda field: isinstance(field, FilterField), cls.get_search_fields())
@classmethod
def get_indexed_objects(cls):
return cls.objects.all()
indexed_fields = ()
warnings.warn(
"The wagtail.wagtailsearch.indexed module has been renamed. "
"Use wagtail.wagtailsearch.index instead.", RemovedInWagtail08Warning)
class BaseField(object):
suffix = ''
def __init__(self, field_name, **kwargs):
self.field_name = field_name
self.kwargs = kwargs
def get_field(self, cls):
return cls._meta.get_field_by_name(self.field_name)[0]
def get_attname(self, cls):
try:
field = self.get_field(cls)
return field.attname
except models.fields.FieldDoesNotExist:
return self.field_name
def get_index_name(self, cls):
return self.get_attname(cls) + self.suffix
def get_type(self, cls):
if 'type' in self.kwargs:
return self.kwargs['type']
try:
field = self.get_field(cls)
return field.get_internal_type()
except models.fields.FieldDoesNotExist:
return 'CharField'
def get_value(self, obj):
try:
field = self.get_field(obj.__class__)
return field._get_val_from_obj(obj)
except models.fields.FieldDoesNotExist:
value = getattr(obj, self.field_name, None)
if hasattr(value, '__call__'):
value = value()
return value
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.field_name)
class SearchField(BaseField):
def __init__(self, field_name, boost=None, partial_match=False, **kwargs):
super(SearchField, self).__init__(field_name, **kwargs)
self.boost = boost
self.partial_match = partial_match
class FilterField(BaseField):
suffix = '_filter'
from .index import *

Wyświetl plik

@ -4,7 +4,6 @@ from django.db import models
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch.utils import normalise_query_string, MAX_QUERY_STRING_LENGTH

Wyświetl plik

@ -2,7 +2,7 @@ from django.db.models.signals import post_save, post_delete
from django.db import models
from django.conf import settings
from wagtail.wagtailsearch.indexed import Indexed
from wagtail.wagtailsearch.index import Indexed
from wagtail.wagtailsearch.backends import get_search_backend

Wyświetl plik

@ -2,7 +2,7 @@ import warnings
from django.test import TestCase
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch import index
from wagtail.tests import models
from wagtail.tests.utils import WagtailTestUtils
@ -30,12 +30,12 @@ class TestIndexedFieldsBackwardsCompatibility(TestCase, WagtailTestUtils):
# Check that the fields were found
self.assertEqual(len(search_fields_dict), 2)
self.assertIn(('title', indexed.SearchField), search_fields_dict.keys())
self.assertIn(('live', indexed.FilterField), search_fields_dict.keys())
self.assertIn(('title', index.SearchField), search_fields_dict.keys())
self.assertIn(('live', index.FilterField), search_fields_dict.keys())
# Check that the title field has the correct settings
self.assertTrue(search_fields_dict[('title', indexed.SearchField)].partial_match)
self.assertEqual(search_fields_dict[('title', indexed.SearchField)].boost, 100)
self.assertTrue(search_fields_dict[('title', index.SearchField)].partial_match)
self.assertEqual(search_fields_dict[('title', index.SearchField)].boost, 100)
def test_indexed_fields_backwards_compatibility_list(self):
# Get search fields
@ -49,5 +49,5 @@ class TestIndexedFieldsBackwardsCompatibility(TestCase, WagtailTestUtils):
# Check that the fields were found
self.assertEqual(len(search_fields_dict), 2)
self.assertIn(('title', indexed.SearchField), search_fields_dict.keys())
self.assertIn(('content', indexed.SearchField), search_fields_dict.keys())
self.assertIn(('title', index.SearchField), search_fields_dict.keys())
self.assertIn(('content', index.SearchField), search_fields_dict.keys())