misc: add ilike operator (#74026) #1088
|
@ -1365,6 +1365,9 @@ def test_api_list_formdata_string_filter(pub, local_user):
|
|||
('existing', 'on', 3),
|
||||
('between', 'FOO 1|FOO 2', 1),
|
||||
('between', 'FOO 2|FOO 1', 1),
|
||||
('icontains', 'FOO', 3),
|
||||
('icontains', 'foo', 3),
|
||||
('icontains', '2', 1),
|
||||
]
|
||||
for operator, value, result in params:
|
||||
resp = get_app(pub).get(
|
||||
|
@ -1541,6 +1544,9 @@ def test_api_list_formdata_text_filter(pub, local_user):
|
|||
('existing', 'on', 3),
|
||||
('between', 'FOO 1|FOO 2', 1),
|
||||
('between', 'FOO 2|FOO 1', 1),
|
||||
('icontains', 'FOO', 3),
|
||||
('icontains', 'foo', 3),
|
||||
('icontains', '2', 1),
|
||||
]
|
||||
for operator, value, result in params:
|
||||
resp = get_app(pub).get(
|
||||
|
@ -2010,6 +2016,8 @@ def test_api_list_formdata_email_filter(pub, local_user):
|
|||
('not_in', 'a@localhost|b@localhost', 1),
|
||||
('absent', 'on', 2),
|
||||
('existing', 'on', 3),
|
||||
('icontains', 'A@LOCAL', 1),
|
||||
('icontains', 'C@LOCAL', 0),
|
||||
]
|
||||
for operator, value, result in params:
|
||||
resp = get_app(pub).get(
|
||||
|
@ -2306,6 +2314,8 @@ def test_api_list_formdata_block_field_filter(pub, local_user):
|
|||
('existing', 'on', 12),
|
||||
('between', 'plop1|plop5', 7),
|
||||
('between', 'plop5|plop1', 7),
|
||||
('icontains', 'PLOP', 12),
|
||||
('icontains', 'LOP1', 4), # plop1 (twice), plop10, plop11
|
||||
]
|
||||
for operator, value, result in params:
|
||||
resp = get_app(pub).get(
|
||||
|
|
|
@ -1048,6 +1048,7 @@ def test_backoffice_string_filter(pub):
|
|||
'not_in',
|
||||
'absent',
|
||||
'existing',
|
||||
'icontains',
|
||||
]
|
||||
|
||||
resp.forms['listing-settings']['filter-4-value'].value = 'a'
|
||||
|
@ -1167,6 +1168,7 @@ def test_backoffice_text_filter(pub):
|
|||
'not_in',
|
||||
'absent',
|
||||
'existing',
|
||||
'icontains',
|
||||
]
|
||||
|
||||
resp.forms['listing-settings']['filter-4-value'].value = 'a'
|
||||
|
@ -1227,6 +1229,7 @@ def test_backoffice_email_filter(pub):
|
|||
'not_in',
|
||||
'absent',
|
||||
'existing',
|
||||
'icontains',
|
||||
]
|
||||
|
||||
resp.forms['listing-settings']['filter-4-value'].value = 'a@localhost'
|
||||
|
@ -1245,6 +1248,12 @@ def test_backoffice_email_filter(pub):
|
|||
assert resp.text.count('>a@localhost</') > 0
|
||||
assert resp.text.count('>b@localhost</') == 0
|
||||
|
||||
resp.forms['listing-settings']['filter-4-value'].value = 'a@local'
|
||||
resp.forms['listing-settings']['filter-4-operator'].value = 'icontains'
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
assert resp.text.count('>a@localhost</') > 0
|
||||
assert resp.text.count('>b@localhost</') == 0
|
||||
|
||||
|
||||
def test_backoffice_date_filter(pub):
|
||||
pub.user_class.wipe()
|
||||
|
@ -1761,6 +1770,7 @@ def test_backoffice_block_field_filter(pub):
|
|||
'not_in',
|
||||
'absent',
|
||||
'existing',
|
||||
'icontains',
|
||||
]
|
||||
resp.forms['listing-settings']['filter-0-1-value'].value = 'plop0'
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
|
@ -1879,6 +1889,7 @@ def test_backoffice_block_field_filter(pub):
|
|||
'not_in',
|
||||
'absent',
|
||||
'existing',
|
||||
'icontains',
|
||||
]
|
||||
resp.forms['listing-settings']['filter-0-5-value'].value = 'a@localhost'
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
|
@ -1893,6 +1904,10 @@ def test_backoffice_block_field_filter(pub):
|
|||
resp.forms['listing-settings']['filter-0-5-operator'].value = 'ne'
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
assert resp.text.count('<tr') == 1 + 4
|
||||
resp.forms['listing-settings']['filter-0-5-value'].value = '@localhost'
|
||||
resp.forms['listing-settings']['filter-0-5-operator'].value = 'icontains'
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
assert resp.text.count('<tr') == 1 + 10
|
||||
|
||||
# mix
|
||||
resp = app.get('/backoffice/management/form-title/')
|
||||
|
|
|
@ -4236,6 +4236,8 @@ def test_formdata_filtering_on_fields(pub):
|
|||
('between', 'plop5|plop1', '4'),
|
||||
('between', ['plop1', 'plop5'], '4'),
|
||||
('between', ['plop5', 'plop1'], '4'),
|
||||
('icontains', 'plop', '10'),
|
||||
('icontains', 'PLOP', '10'),
|
||||
]
|
||||
for operator, value, result in params:
|
||||
context['value'] = None
|
||||
|
@ -4494,6 +4496,8 @@ def test_formdata_filtering_on_fields(pub):
|
|||
('not_in', 'a@localhost|b@localhost', '1'),
|
||||
('absent', '', '2'),
|
||||
('existing', '', '10'),
|
||||
('icontains', 'A@local', '5'),
|
||||
('icontains', '@LOCAL', '10'),
|
||||
]
|
||||
for operator, value, result in params:
|
||||
if value:
|
||||
|
@ -4543,6 +4547,8 @@ def test_formdata_filtering_on_fields(pub):
|
|||
('between', 'plop5|plop1', '4'),
|
||||
('between', ['plop1', 'plop5'], '4'),
|
||||
('between', ['plop5', 'plop1'], '4'),
|
||||
('icontains', 'plop', '10'),
|
||||
('icontains', 'PLOP', '10'),
|
||||
]
|
||||
for operator, value, result in params:
|
||||
context['value'] = None
|
||||
|
|
|
@ -922,6 +922,11 @@ def between(queryset):
|
|||
return queryset.apply_between()
|
||||
|
||||
|
||||
@register_queryset_filter(name='icontains', attr='apply_icontains')
|
||||
def icontains(queryset):
|
||||
return queryset.apply_icontains()
|
||||
|
||||
|
||||
@register.filter
|
||||
def count(queryset):
|
||||
if hasattr(queryset, '__len__'):
|
||||
|
|
|
@ -25,7 +25,7 @@ from wcs.qommon import misc
|
|||
|
||||
|
||||
def like_escape(value):
|
||||
value = value.replace('\\', '\\\\')
|
||||
value = str(value or '').replace('\\', '\\\\')
|
||||
value = value.replace('_', '\\_')
|
||||
value = value.replace('%', '\\%')
|
||||
return value
|
||||
|
@ -336,13 +336,12 @@ class Intersects(Criteria):
|
|||
|
||||
|
||||
class ILike(Criteria):
|
||||
sql_op = 'ILIKE'
|
||||
|
||||
def __init__(self, attribute, value, **kwargs):
|
||||
super().__init__(attribute, value, **kwargs)
|
||||
self.value = '%' + like_escape(self.value) + '%'
|
||||
|
||||
def as_sql(self):
|
||||
return '%s ILIKE %%(c%s)s' % (self.attribute, id(self.value))
|
||||
|
||||
|
||||
class FtsMatch(Criteria):
|
||||
def __init__(self, value, extra_normalize=True, **kwargs):
|
||||
|
|
|
@ -30,6 +30,7 @@ from wcs.sql_criterias import (
|
|||
Equal,
|
||||
Greater,
|
||||
GreaterOrEqual,
|
||||
ILike,
|
||||
Less,
|
||||
LessOrEqual,
|
||||
Not,
|
||||
|
@ -303,9 +304,21 @@ class LazyFormDefObjectsManager:
|
|||
('in', _('in')),
|
||||
('not_in', _('not in')),
|
||||
]
|
||||
text_operators = [
|
||||
('icontains', _('contains')),
|
||||
]
|
||||
if field.key == 'internal-id':
|
||||
return equality_operators + comparison_operators
|
||||
if field.key in ['date', 'item', 'items', 'string', 'text', 'numeric']:
|
||||
if field.key in ['string', 'text']:
|
||||
return (
|
||||
equality_operators
|
||||
+ comparison_operators
|
||||
+ more_comparison_operators
|
||||
+ in_operators
|
||||
+ empty_operators
|
||||
+ text_operators
|
||||
)
|
||||
if field.key in ['date', 'item', 'items', 'numeric']:
|
||||
return (
|
||||
equality_operators
|
||||
+ comparison_operators
|
||||
|
@ -316,7 +329,7 @@ class LazyFormDefObjectsManager:
|
|||
if field.key == 'bool':
|
||||
return equality_operators + empty_operators
|
||||
if field.key == 'email':
|
||||
return equality_operators + in_operators + empty_operators
|
||||
return equality_operators + in_operators + empty_operators + text_operators
|
||||
return None
|
||||
|
||||
def format_value(self, op, value, field):
|
||||
|
@ -412,6 +425,7 @@ class LazyFormDefObjectsManager:
|
|||
'gt': Greater,
|
||||
'gte': GreaterOrEqual,
|
||||
'in': Contains,
|
||||
'icontains': ILike,
|
||||
}
|
||||
|
||||
if isinstance(value, list) and op in ['eq', 'ne']:
|
||||
|
@ -588,6 +602,9 @@ class LazyFormDefObjectsManager:
|
|||
def apply_between(self):
|
||||
return self.apply_op('between')
|
||||
|
||||
def apply_icontains(self):
|
||||
return self.apply_op('icontains')
|
||||
|
||||
def getlist(self, key):
|
||||
return LazyList(self, key)
|
||||
|
||||
|
|
Loading…
Reference in New Issue