diff --git a/wagtail/wagtailsearch/tests/test_queries.py b/wagtail/wagtailsearch/tests/test_queries.py index afc0f02175..400d2494a0 100644 --- a/wagtail/wagtailsearch/tests/test_queries.py +++ b/wagtail/wagtailsearch/tests/test_queries.py @@ -3,13 +3,13 @@ from __future__ import absolute_import, unicode_literals import datetime from django.core import management -from django.test import TestCase +from django.test import SimpleTestCase, TestCase from django.utils.six import StringIO from wagtail.contrib.wagtailsearchpromotions.models import SearchPromotion from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailsearch import models -from wagtail.wagtailsearch.utils import normalise_query_string +from wagtail.wagtailsearch.utils import normalise_query_string, separate_filters_from_query class TestHitCounter(TestCase): @@ -176,3 +176,47 @@ class TestQueryChooserView(TestCase, WagtailTestUtils): for page in pages: response = self.get({'p': page}) self.assertEqual(response.status_code, 200) + + +class TestSeparateFiltersFromQuery(SimpleTestCase): + def test_only_query(self): + filters, query = separate_filters_from_query('hello world') + + self.assertDictEqual(filters, {}) + self.assertEquals(query, 'hello world') + + def test_filter(self): + filters, query = separate_filters_from_query('author:foo') + + self.assertDictEqual(filters, {'author': 'foo'}) + self.assertEquals(query, '') + + def test_filter_with_quotation_mark(self): + filters, query = separate_filters_from_query('author:"foo bar"') + + self.assertDictEqual(filters, {'author': 'foo bar'}) + self.assertEquals(query, '') + + def test_filter_and_query(self): + filters, query = separate_filters_from_query('author:foo hello world') + + self.assertDictEqual(filters, {'author': 'foo'}) + self.assertEquals(query, 'hello world') + + def test_filter_with_quotation_mark_and_query(self): + filters, query = separate_filters_from_query('author:"foo bar" hello world') + + self.assertDictEqual(filters, {'author': 'foo bar'}) + self.assertEquals(query, 'hello world') + + def test_filter_with_unclosed_quotation_mark_and_query(self): + filters, query = separate_filters_from_query('author:"foo bar hello world') + + self.assertDictEqual(filters, {}) + self.assertEquals(query, 'author:"foo bar hello world') + + def test_two_filters_and_query(self): + filters, query = separate_filters_from_query('author:"foo bar" hello world bar:beer') + + self.assertDictEqual(filters, {'author': 'foo bar', 'bar': 'beer'}) + self.assertEquals(query, 'hello world') diff --git a/wagtail/wagtailsearch/utils.py b/wagtail/wagtailsearch/utils.py index 1036829aa1..495a58833f 100644 --- a/wagtail/wagtailsearch/utils.py +++ b/wagtail/wagtailsearch/utils.py @@ -1,5 +1,6 @@ from __future__ import absolute_import, unicode_literals +import re import string MAX_QUERY_STRING_LENGTH = 255 @@ -19,3 +20,16 @@ def normalise_query_string(query_string): query_string = ' '.join(query_string.split()) return query_string + + +def separate_filters_from_query(query_string): + filters_regexp = r'(\w+):(\w+|".+")' + + filters = {} + for match_object in re.finditer(filters_regexp, query_string): + key, value = match_object.groups() + filters[key] = value.strip("\"") + + query_string = re.sub(filters_regexp, '', query_string).strip() + + return filters, query_string