wcs: add operators (#70125)

This commit is contained in:
Lauréline Guérin 2022-10-13 15:50:52 +02:00
parent a08f263abd
commit 270e0b51dc
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
3 changed files with 178 additions and 55 deletions

View File

@ -90,31 +90,60 @@ class LazyCardDefObjectsManager:
value = ''
if isinstance(value, bool):
value = str(value).lower()
op = getattr(self, 'pending_op', 'eq')
if self.pending_attr in ['internal_id', 'number', 'user', 'status']:
return getattr(self, 'filter_by_%s' % self.pending_attr)(value, op)
qs._filters['filter-%s' % self.pending_attr] = value
qs._filters['filter-%s-operator' % self.pending_attr] = op
return qs
def filter_by_internal_id(self, internal_id):
def apply_op(self, op):
self.pending_op = op
return self
def apply_eq(self):
return self.apply_op('eq')
def apply_ne(self):
return self.apply_op('ne')
def apply_lt(self):
return self.apply_op('lt')
def apply_lte(self):
return self.apply_op('lte')
def apply_gt(self):
return self.apply_op('gt')
def apply_gte(self):
return self.apply_op('gte')
def filter_by_internal_id(self, internal_id, op='eq'):
qs = self._clone()
if internal_id:
qs._filters['filter-internal-id'] = internal_id
qs._filters['filter-internal-id-operator'] = op
return qs
def filter_by_number(self, number):
def filter_by_number(self, number, op='eq'):
qs = self._clone()
if number:
qs._filters['filter-number'] = number
return qs
def filter_by_user(self, user):
def filter_by_user(self, user, op='eq'):
qs = self._clone()
if user and user.is_authenticated and user.get_name_id():
qs._filters['filter-user-uuid'] = user.get_name_id()
return qs
def filter_by_status(self, status):
def filter_by_status(self, status, op='eq'):
qs = self._clone()
if status:
qs._filters['filter'] = status
if op in ['eq', 'ne']:
qs._filters['filter-operator'] = op
return qs
def _get_results_from_wcs(self):

View File

@ -74,6 +74,36 @@ def filter_by_status(queryset, status):
return queryset.filter_by_status(status)
@register.filter(name='equal')
def eq(queryset):
return queryset.apply_eq()
@register.filter(name='not_equal')
def ne(queryset):
return queryset.apply_ne()
@register.filter(name='less_than')
def lt(queryset):
return queryset.apply_lt()
@register.filter(name='less_than_or_equal')
def lte(queryset):
return queryset.apply_lte()
@register.filter(name='greater_than')
def gt(queryset):
return queryset.apply_gt()
@register.filter(name='greater_than_or_equal')
def gte(queryset):
return queryset.apply_gte()
@register.filter
def order_by(queryset, attribute):
return queryset.order_by(attribute)

View File

@ -236,6 +236,16 @@ def test_count(mock_send, context, nocache):
assert t.render(context) == "2"
OPERATORS = [
('equal', 'eq'),
('not_equal', 'ne'),
('less_than', 'lt'),
('less_than_or_equal', 'lte'),
('greater_than', 'gt'),
('greater_than_or_equal', 'gte'),
]
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|filter_by:"foo"|filter_value:"bar"|list }}')
@ -266,6 +276,13 @@ def test_filter(mock_send, context, nocache):
t.render(context)
assert 'filter-foo=&' in mock_send.call_args_list[0][0][0].url
for filter_op, api_op in OPERATORS:
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by:"foo"|%s|filter_value:"bar"|list }}' % filter_op)
t.render(context)
assert 'filter-foo=bar&' in mock_send.call_args_list[0][0][0].url
assert 'filter-foo-operator=%s&' % api_op in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter_by_internal_id(mock_send, context, nocache):
@ -273,20 +290,30 @@ def test_filter_by_internal_id(mock_send, context, nocache):
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_internal_id:None|list }}')
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
for tpl in ['filter_by_internal_id', 'filter_by:"internal_id"|filter_value']:
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:None|list }}' % tpl)
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_internal_id:""|list }}')
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:""|list }}' % tpl)
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_internal_id:"42"|list }}')
t.render(context)
assert 'filter-internal-id=42&' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:"42"|list }}' % tpl)
t.render(context)
assert 'filter-internal-id=42&' in mock_send.call_args_list[0][0][0].url
for filter_op, api_op in OPERATORS:
mock_send.reset_mock()
t = Template(
'{{ cards|objects:"foo"|filter_by:"internal_id"|%s|filter_value:"42"|list }}' % filter_op
)
t.render(context)
assert 'filter-internal-id=42&' in mock_send.call_args_list[0][0][0].url
assert 'filter-internal-id-operator=%s&' % api_op in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
@ -295,42 +322,64 @@ def test_filter_by_number(mock_send, context, nocache):
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_number:None|list }}')
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
for tpl in ['filter_by_number', 'filter_by:"number"|filter_value']:
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:None|list }}' % tpl)
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_number:""|list }}')
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:""|list }}' % tpl)
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_number:"42-35"|list }}')
t.render(context)
assert 'filter-number=42-35&' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:"42-35"|list }}' % tpl)
t.render(context)
assert 'filter-number=42-35&' in mock_send.call_args_list[0][0][0].url
for filter_op, api_op in OPERATORS:
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by:"number"|%s|filter_value:"42-35"|list }}' % filter_op)
t.render(context)
assert 'filter-number=42-35&' in mock_send.call_args_list[0][0][0].url
# not for this filter
assert 'filter-number-operator=%s&' % api_op not in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter_by_user(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|filter_by_user:request.user|list }}')
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
for tpl in ['filter_by_user', 'filter_by:"user"|filter_value']:
t = Template('{{ cards|objects:"foo"|%s:request.user|list }}' % tpl)
mock_send.reset_mock()
context['request'].user = None
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockAnonymousUser()
mock_send.reset_mock()
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockAnonymousUser()
mock_send.reset_mock()
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
t.render(context)
assert 'filter-user-uuid=xyz&' in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
t.render(context)
assert 'filter-user-uuid=xyz&' in mock_send.call_args_list[0][0][0].url
for filter_op, api_op in OPERATORS:
mock_send.reset_mock()
t = Template(
'{{ cards|objects:"foo"|filter_by:"user"|%s|filter_value:request.user|list }}' % filter_op
)
t.render(context)
assert 'filter-user-uuid=xyz&' in mock_send.call_args_list[0][0][0].url
# not for this filter
assert 'filter-user-uuid-operator=%s&' % api_op not in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
@ -338,21 +387,36 @@ def test_filter_by_status(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
assert 'filter-operator=eq&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_status:None|list }}')
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
for tpl in ['filter_by_status', 'filter_by:"status"|filter_value']:
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:None|list }}' % tpl)
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
assert 'filter-operator=eq&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_status:""|list }}')
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:""|list }}' % tpl)
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
assert 'filter-operator=eq&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_status:"foobar"|list }}')
t.render(context)
assert 'filter=foobar&' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|%s:"foobar"|list }}' % tpl)
t.render(context)
assert 'filter=foobar&' in mock_send.call_args_list[0][0][0].url
assert 'filter-operator=eq&' in mock_send.call_args_list[0][0][0].url
for filter_op, api_op in OPERATORS:
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by:"status"|%s|filter_value:"foobar"|list }}' % filter_op)
t.render(context)
assert 'filter=foobar&' in mock_send.call_args_list[0][0][0].url
if api_op in ['eq', 'ne']:
assert 'filter-operator=%s&' % api_op in mock_send.call_args_list[0][0][0].url
else:
assert 'filter-operator=%s&' % api_op not in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)