From 54bb9e2869336ca72e445b56cf7d854064b10690 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Thu, 12 Jun 2014 20:41:25 -0700 Subject: [PATCH] Add experimental soundex filter support to the Customers grid. --- tailbone/grids/search.py | 37 +++++++++++++++++++++++++++++---- tailbone/views/customers.py | 7 +++---- tailbone/views/grids/alchemy.py | 11 +++++++--- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/tailbone/grids/search.py b/tailbone/grids/search.py index 00e166a4..95341207 100644 --- a/tailbone/grids/search.py +++ b/tailbone/grids/search.py @@ -1,9 +1,8 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2012 Lance Edgar +# Copyright © 2010-2014 Lance Edgar # # This file is part of Rattail. # @@ -26,7 +25,7 @@ Grid Search Filters """ -from sqlalchemy import or_ +from sqlalchemy import func, or_ from webhelpers.html import tags from webhelpers.html import literal @@ -55,6 +54,8 @@ class SearchFilter(Object): ('nt', "is not"), ('lk', "contains"), ('nl', "doesn't contain"), + (u'sx', u"sounds like"), + (u'nx', u"doesn't sound like"), ] options = [] filter_map = self.search.filter_map[self.name] @@ -179,6 +180,34 @@ def filter_ilike(field): return {'lk': ilike, 'nl': not_ilike} +def filter_soundex(field): + """ + Returns a filter map entry which leverages the `soundex()` SQL function. + """ + + def soundex(query, value): + if value: + query = query.filter(func.soundex(field) == func.soundex(value)) + return query + + def not_soundex(query, value): + if value: + query = query.filter(func.soundex(field) != func.soundex(value)) + return query + + return {u'sx': soundex, u'nx': not_soundex} + + +def filter_ilike_and_soundex(field): + """ + Returns a filter map which provides both the `ilike` and `soundex` + features. + """ + filters = filter_ilike(field) + filters.update(filter_soundex(field)) + return filters + + def get_filter_config(prefix, request, filter_map, **kwargs): """ Returns a configuration dictionary for a search form. diff --git a/tailbone/views/customers.py b/tailbone/views/customers.py index f6ada2c3..0a41ade6 100644 --- a/tailbone/views/customers.py +++ b/tailbone/views/customers.py @@ -1,9 +1,8 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2012 Lance Edgar +# Copyright © 2010-2014 Lance Edgar # # This file is part of Rattail. # @@ -58,7 +57,7 @@ class CustomersGrid(SearchableAlchemyGridView): def filter_map(self): return self.make_filter_map( exact=['id'], - ilike=['name'], + name=self.filter_ilike_and_soundex(model.Customer.name), email=self.filter_ilike(model.CustomerEmailAddress.address), phone=self.filter_ilike(model.CustomerPhoneNumber.number)) diff --git a/tailbone/views/grids/alchemy.py b/tailbone/views/grids/alchemy.py index 9f0ada45..3cfc8a89 100644 --- a/tailbone/views/grids/alchemy.py +++ b/tailbone/views/grids/alchemy.py @@ -1,9 +1,8 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2012 Lance Edgar +# Copyright © 2010-2014 Lance Edgar # # This file is part of Rattail. # @@ -139,6 +138,12 @@ class SearchableAlchemyGridView(PagedAlchemyGridView): def filter_ilike(self, field): return grids.search.filter_ilike(field) + def filter_soundex(self, field): + return grids.search.filter_soundex(field) + + def filter_ilike_and_soundex(self, field): + return grids.search.filter_ilike_and_soundex(field) + def make_filter_map(self, **kwargs): return grids.search.get_filter_map(self.mapped_class, **kwargs)