Add the "has" DB filter

* This filter is needed for search functionality when we don't need
  to rely on full match. Instead, we should be able to find entities
  by inclusion of a value into a specified field.

Change-Id: I2133493e5b79b59994c7ef6b0e50b6ba1e1d37c6
This commit is contained in:
Renat Akhmerov 2016-12-27 18:30:33 +07:00
parent daa06e06ee
commit 815c4a7989
3 changed files with 30 additions and 0 deletions

View File

@ -20,6 +20,7 @@ def apply_filters(query, model, **filters):
for key, value in filters.items(): for key, value in filters.items():
column_attr = getattr(model, key) column_attr = getattr(model, key)
if isinstance(value, dict): if isinstance(value, dict):
if 'in' in value: if 'in' in value:
query = query.filter(column_attr.in_(value['in'])) query = query.filter(column_attr.in_(value['in']))
@ -37,6 +38,10 @@ def apply_filters(query, model, **filters):
query = query.filter(column_attr <= value['lte']) query = query.filter(column_attr <= value['lte'])
elif 'eq' in value: elif 'eq' in value:
query = query.filter(column_attr == value['eq']) query = query.filter(column_attr == value['eq'])
elif 'has' in value:
like_pattern = '%{0}%'.format(value['has'])
query = query.filter(column_attr.like(like_pattern))
else: else:
filter_dict[key] = value filter_dict[key] = value

View File

@ -1045,6 +1045,24 @@ class ActionDefinitionTest(SQLAlchemyTest):
self.assertEqual(0, len(fetched)) self.assertEqual(0, len(fetched))
def test_filter_action_definitions_by_has_filter(self):
db_api.create_action_definition(ACTION_DEFINITIONS[0])
db_api.create_action_definition(ACTION_DEFINITIONS[1])
created3 = db_api.create_action_definition(ACTION_DEFINITIONS[2])
f = filter_utils.create_or_update_filter('name', "3", 'has')
fetched = db_api.get_action_definitions(**f)
self.assertEqual(1, len(fetched))
self.assertEqual(created3, fetched[0])
f = filter_utils.create_or_update_filter('name', "Action", 'has')
fetched = db_api.get_action_definitions(**f)
self.assertEqual(3, len(fetched))
def test_update_action_definition_with_name(self): def test_update_action_definition_with_name(self):
created = db_api.create_action_definition(ACTION_DEFINITIONS[0]) created = db_api.create_action_definition(ACTION_DEFINITIONS[0])

View File

@ -22,13 +22,16 @@ def create_filters_from_request_params(**params):
:return: filters dictionary. :return: filters dictionary.
""" """
filters = {} filters = {}
for column, data in params.items(): for column, data in params.items():
if data is not None: if data is not None:
if isinstance(data, six.string_types): if isinstance(data, six.string_types):
f_type, value = _extract_filter_type_and_value(data) f_type, value = _extract_filter_type_and_value(data)
create_or_update_filter(column, value, f_type, filters) create_or_update_filter(column, value, f_type, filters)
else: else:
create_or_update_filter(column, data, _filter=filters) create_or_update_filter(column, data, _filter=filters)
return filters return filters
@ -47,6 +50,7 @@ def create_or_update_filter(column, value, filter_type='eq', _filter=None):
""" """
if _filter is None: if _filter is None:
_filter = {} _filter = {}
_filter[column] = {filter_type: value} _filter[column] = {filter_type: value}
return _filter return _filter
@ -84,6 +88,9 @@ def _extract_filter_type_and_value(data):
elif data.startswith("eq:"): elif data.startswith("eq:"):
value = six.text_type(data[3:]) value = six.text_type(data[3:])
filter_type = 'eq' filter_type = 'eq'
elif data.startswith("has:"):
value = six.text_type(data[4:])
filter_type = 'has'
else: else:
value = data value = data
filter_type = 'eq' filter_type = 'eq'