Don't search blindly for all the fields passed in the advanced search, use the defined fields, avoid hard coded rejection of &page arguments in the query string. The SearchModel class is now responsible for storing the search in the recent entries instead of the view.
This commit is contained in:
@@ -49,16 +49,8 @@ class APISearchView(generics.ListAPIView):
|
|||||||
self.mayan_object_permissions = {'GET': [document_search.permission]}
|
self.mayan_object_permissions = {'GET': [document_search.permission]}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if 'q' in self.request.GET:
|
queryset, ids, timedelta = document_search.search(self.request.GET, self.request.user)
|
||||||
# Simple query
|
|
||||||
query_string = self.request.GET.get('q', u'').strip()
|
|
||||||
queryset, ids, timedelta = document_search.simple_search(query_string)
|
|
||||||
else:
|
|
||||||
# Advanced search
|
|
||||||
queryset, ids, timedelta = document_search.advanced_search(self.request.GET)
|
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
raise ParseError(unicode(exception))
|
raise ParseError(unicode(exception))
|
||||||
|
|
||||||
RecentSearch.objects.add_query_for_user(self.request.user, self.request.GET, len(ids))
|
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from acls.models import AccessEntry
|
|||||||
from common.utils import load_backend
|
from common.utils import load_backend
|
||||||
from permissions.models import Permission
|
from permissions.models import Permission
|
||||||
|
|
||||||
|
from .models import RecentSearch
|
||||||
from .settings import LIMIT
|
from .settings import LIMIT
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -67,14 +68,6 @@ class SearchModel(object):
|
|||||||
search_field = SearchField(self, *args, **kwargs)
|
search_field = SearchField(self, *args, **kwargs)
|
||||||
self.search_fields[search_field.get_full_name()] = search_field
|
self.search_fields[search_field.get_full_name()] = search_field
|
||||||
|
|
||||||
def add_related_field(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Add a search field that will search content in a related field in
|
|
||||||
a separate model
|
|
||||||
"""
|
|
||||||
search_field = RelatedSearchField(self, *args, **kwargs)
|
|
||||||
self.search_fields[search_field.get_full_name()] = search_field
|
|
||||||
|
|
||||||
def normalize_query(self, query_string,
|
def normalize_query(self, query_string,
|
||||||
findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
|
findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
|
||||||
normspace=re.compile(r'\s{2,}').sub):
|
normspace=re.compile(r'\s{2,}').sub):
|
||||||
@@ -87,38 +80,15 @@ class SearchModel(object):
|
|||||||
"""
|
"""
|
||||||
return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
|
return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
|
||||||
|
|
||||||
def simple_search(self, query_string, user):
|
def search(self, query_string, user, global_and_search=False):
|
||||||
|
elapsed_time = 0
|
||||||
|
start_time = datetime.datetime.now()
|
||||||
|
result_set = set()
|
||||||
search_dict = {}
|
search_dict = {}
|
||||||
|
|
||||||
for search_field in self.get_all_search_fields():
|
if 'q' in query_string:
|
||||||
search_dict.setdefault(search_field.get_model(), {
|
# Simple search
|
||||||
'searches': [],
|
for search_field in self.get_all_search_fields():
|
||||||
'label': search_field.label,
|
|
||||||
'return_value': search_field.return_value
|
|
||||||
})
|
|
||||||
search_dict[search_field.get_model()]['searches'].append(
|
|
||||||
{
|
|
||||||
'field_name': [search_field.field],
|
|
||||||
'terms': self.normalize_query(query_string)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug('search_dict: %s', search_dict)
|
|
||||||
|
|
||||||
return self.execute_search(search_dict, user=user, global_and_search=False)
|
|
||||||
|
|
||||||
def advanced_search(self, dictionary, user):
|
|
||||||
search_dict = {}
|
|
||||||
|
|
||||||
for key, value in dictionary.items():
|
|
||||||
logger.debug('key: %s', key)
|
|
||||||
logger.debug('value: %s', value)
|
|
||||||
|
|
||||||
if key == 'page':
|
|
||||||
continue
|
|
||||||
if value:
|
|
||||||
search_field = self.get_search_field(key)
|
|
||||||
logger.debug('search_field: %s', search_field)
|
|
||||||
search_dict.setdefault(search_field.get_model(), {
|
search_dict.setdefault(search_field.get_model(), {
|
||||||
'searches': [],
|
'searches': [],
|
||||||
'label': search_field.label,
|
'label': search_field.label,
|
||||||
@@ -127,18 +97,24 @@ class SearchModel(object):
|
|||||||
search_dict[search_field.get_model()]['searches'].append(
|
search_dict[search_field.get_model()]['searches'].append(
|
||||||
{
|
{
|
||||||
'field_name': [search_field.field],
|
'field_name': [search_field.field],
|
||||||
'terms': self.normalize_query(value)
|
'terms': self.normalize_query(query_string.get('q', u'').strip())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
|
||||||
logger.debug('search_dict: %s', search_dict)
|
for search_field in self.get_all_search_fields():
|
||||||
|
if search_field.field in query_string and query_string[search_field.field]:
|
||||||
return self.execute_search(search_dict, user=user, global_and_search=True)
|
search_dict.setdefault(search_field.get_model(), {
|
||||||
|
'searches': [],
|
||||||
def execute_search(self, search_dict, user, global_and_search=False):
|
'label': search_field.label,
|
||||||
elapsed_time = 0
|
'return_value': search_field.return_value
|
||||||
start_time = datetime.datetime.now()
|
})
|
||||||
result_set = set()
|
search_dict[search_field.get_model()]['searches'].append(
|
||||||
|
{
|
||||||
|
'field_name': [search_field.field],
|
||||||
|
'terms': self.normalize_query(query_string[search_field.field])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
for model, data in search_dict.items():
|
for model, data in search_dict.items():
|
||||||
logger.debug('model: %s', model)
|
logger.debug('model: %s', model)
|
||||||
@@ -194,6 +170,8 @@ class SearchModel(object):
|
|||||||
except PermissionDenied:
|
except PermissionDenied:
|
||||||
queryset = AccessEntry.objects.filter_objects_by_access(self.permission, user, queryset)
|
queryset = AccessEntry.objects.filter_objects_by_access(self.permission, user, queryset)
|
||||||
|
|
||||||
|
RecentSearch.objects.add_query_for_user(user, query_string, len(result_set))
|
||||||
|
|
||||||
return queryset, result_set, elapsed_time
|
return queryset, result_set, elapsed_time
|
||||||
|
|
||||||
def assemble_query(self, terms, search_fields):
|
def assemble_query(self, terms, search_fields):
|
||||||
@@ -231,23 +209,3 @@ class SearchField(object):
|
|||||||
|
|
||||||
def get_model(self):
|
def get_model(self):
|
||||||
return self.search_model.model
|
return self.search_model.model
|
||||||
|
|
||||||
|
|
||||||
class RelatedSearchField(object):
|
|
||||||
"""
|
|
||||||
Search for terms in fields that are related to the parent SearchModel
|
|
||||||
"""
|
|
||||||
def __init__(self, search_model, app_label, model_name, field, return_value, label):
|
|
||||||
self.search_model = search_model
|
|
||||||
self.app_label = app_label
|
|
||||||
self.model_name = model_name
|
|
||||||
self.field = field
|
|
||||||
self.return_value = return_value
|
|
||||||
self.model = get_model(app_label, model_name)
|
|
||||||
self.label = label
|
|
||||||
|
|
||||||
def get_full_name(self):
|
|
||||||
return '%s.%s.%s' % (self.app_label, self.model_name, self.field)
|
|
||||||
|
|
||||||
def get_model(self):
|
|
||||||
return self.model
|
|
||||||
|
|||||||
@@ -10,15 +10,16 @@ from .settings import RECENT_COUNT
|
|||||||
|
|
||||||
|
|
||||||
class RecentSearchManager(models.Manager):
|
class RecentSearchManager(models.Manager):
|
||||||
def add_query_for_user(self, user, query, hits):
|
def add_query_for_user(self, user, query_string, hits):
|
||||||
parsed_query = urlparse.parse_qs(urlencode(dict(query.items())))
|
parsed_query = urlparse.parse_qs(urlencode(dict(query_string.items())))
|
||||||
|
|
||||||
for key, value in parsed_query.items():
|
for key, value in parsed_query.items():
|
||||||
parsed_query[key] = ' '.join(value)
|
parsed_query[key] = ' '.join(value)
|
||||||
|
|
||||||
if 'q=' in query:
|
if 'q' in query_string:
|
||||||
# Is a simple query
|
# Is a simple query
|
||||||
if not parsed_query.get('q'):
|
|
||||||
|
if not query_string['q']:
|
||||||
# Don't store empty simple searches
|
# Don't store empty simple searches
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from django.db import models
|
|||||||
from django.utils.encoding import smart_str, smart_unicode
|
from django.utils.encoding import smart_str, smart_unicode
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from .classes import SearchModel
|
|
||||||
from .managers import RecentSearchManager
|
from .managers import RecentSearchManager
|
||||||
|
|
||||||
|
|
||||||
@@ -30,6 +29,8 @@ class RecentSearch(models.Model):
|
|||||||
objects = RecentSearchManager()
|
objects = RecentSearchManager()
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
|
# TODO: Fix this hack, store the search model name in the recent search entry
|
||||||
|
from .classes import SearchModel
|
||||||
document_search = SearchModel.get('documents.Document')
|
document_search = SearchModel.get('documents.Document')
|
||||||
|
|
||||||
query_dict = urlparse.parse_qs(urllib.unquote_plus(smart_str(self.query)))
|
query_dict = urlparse.parse_qs(urllib.unquote_plus(smart_str(self.query)))
|
||||||
@@ -38,9 +39,8 @@ class RecentSearch(models.Model):
|
|||||||
# Advanced search
|
# Advanced search
|
||||||
advanced_string = []
|
advanced_string = []
|
||||||
for key, value in query_dict.items():
|
for key, value in query_dict.items():
|
||||||
if key != 'page':
|
search_field = document_search.get_search_field(key)
|
||||||
search_field = document_search.get_search_field(key)
|
advanced_string.append(u'%s: %s' % (search_field.label, smart_unicode(' '.join(value))))
|
||||||
advanced_string.append(u'%s: %s' % (search_field.label, smart_unicode(' '.join(value))))
|
|
||||||
|
|
||||||
display_string = u', '.join(advanced_string)
|
display_string = u', '.join(advanced_string)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -34,15 +34,7 @@ def results(request, extra_context=None):
|
|||||||
# Only do search if there is user input, otherwise just render
|
# Only do search if there is user input, otherwise just render
|
||||||
# the template with the extra_context
|
# the template with the extra_context
|
||||||
|
|
||||||
if 'q' in request.GET:
|
queryset, ids, timedelta = document_search.search(request.GET, request.user)
|
||||||
# Simple query
|
|
||||||
logger.debug('simple search')
|
|
||||||
query_string = request.GET.get('q', u'').strip()
|
|
||||||
queryset, ids, timedelta = document_search.simple_search(query_string)
|
|
||||||
else:
|
|
||||||
# Advanced search
|
|
||||||
logger.debug('advanced search')
|
|
||||||
queryset, ids, timedelta = document_search.advanced_search(request.GET)
|
|
||||||
|
|
||||||
# Update the context with the search results
|
# Update the context with the search results
|
||||||
context.update({
|
context.update({
|
||||||
@@ -51,8 +43,6 @@ def results(request, extra_context=None):
|
|||||||
'title': _(u'Results'),
|
'title': _(u'Results'),
|
||||||
})
|
})
|
||||||
|
|
||||||
RecentSearch.objects.add_query_for_user(request.user, document_search, request.GET, len(ids))
|
|
||||||
|
|
||||||
if extra_context:
|
if extra_context:
|
||||||
context.update(extra_context)
|
context.update(extra_context)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user