Add new 'bytestring' filter for grids that need it

For now, must explicitly request the filter, nothing will use it by default
This commit is contained in:
Lance Edgar 2016-12-07 16:00:36 -06:00
parent 457ce97f4e
commit 5a24c4113f

View file

@ -179,12 +179,15 @@ class GridFilter(object):
current verb/value by default. current verb/value by default.
""" """
verb = verb or self.verb verb = verb or self.verb
value = value if value is not UNSPECIFIED else self.value value = self.get_value(value)
filtr = getattr(self, 'filter_{0}'.format(verb), None) filtr = getattr(self, 'filter_{0}'.format(verb), None)
if not filtr: if not filtr:
raise ValueError("Unknown filter verb: {0}".format(repr(verb))) raise ValueError("Unknown filter verb: {0}".format(repr(verb)))
return filtr(data, value) return filtr(data, value)
def get_value(self, value=UNSPECIFIED):
return value if value is not UNSPECIFIED else self.value
def filter_is_any(self, data, value): def filter_is_any(self, data, value):
""" """
Special no-op filter which does no actual filtering. Useful in some Special no-op filter which does no actual filtering. Useful in some
@ -300,7 +303,7 @@ class AlchemyStringFilter(AlchemyGridFilter):
if value is None or value == '': if value is None or value == '':
return query return query
return query.filter(sa.and_( return query.filter(sa.and_(
*[self.column.ilike('%{0}%'.format(v)) for v in value.split()])) *[self.column.ilike('%{}%'.format(v)) for v in value.split()]))
def filter_does_not_contain(self, query, value): def filter_does_not_contain(self, query, value):
""" """
@ -318,6 +321,45 @@ class AlchemyStringFilter(AlchemyGridFilter):
)) ))
class AlchemyByteStringFilter(AlchemyStringFilter):
"""
String filter for SQLAlchemy, which encodes value as bytestring before
passing it along to the query. Useful when querying certain databases
(esp. via FreeTDS) which like to throw the occasional segfault...
"""
value_encoding = 'utf-8'
def get_value(self, value=UNSPECIFIED):
value = super(AlchemyByteStringFilter, self).get_value(value)
if isinstance(value, unicode):
value = value.encode(self.value_encoding)
return value
def filter_contains(self, query, value):
"""
Filter data with a full 'ILIKE' query.
"""
if value is None or value == '':
return query
return query.filter(sa.and_(
*[self.column.ilike(b'%{}%'.format(v)) for v in value.split()]))
def filter_does_not_contain(self, query, value):
"""
Filter data with a full 'NOT ILIKE' query.
"""
if value is None or value == '':
return query
# When saying something is 'not like' something else, we must also
# include things which are nothing at all, in our result set.
return query.filter(sa.or_(
self.column == None,
sa.and_(
*[~self.column.ilike(b'%{}%'.format(v)) for v in value.split()]),
))
class AlchemyNumericFilter(AlchemyGridFilter): class AlchemyNumericFilter(AlchemyGridFilter):
""" """
Numeric filter for SQLAlchemy. Numeric filter for SQLAlchemy.