diff --git a/tests/test_carddef.py b/tests/test_carddef.py index cad77ad06..51180f368 100644 --- a/tests/test_carddef.py +++ b/tests/test_carddef.py @@ -1273,3 +1273,7 @@ def test_card_custom_id(pub, ids): pub.substitutions.feed(card) context = pub.substitutions.get_context_variables(mode='lazy') assert context['form_identifier'] == str(ids[-1]) + + context = pub.substitutions.get_context_variables(mode='lazy') + tmpl = Template('{{ cards|objects:"foo"|filter_by_identifier:"%s"|count }}' % ids[-1]) + assert tmpl.render(context) == '1' diff --git a/tests/test_formdata.py b/tests/test_formdata.py index 2615a9e9e..3607de571 100644 --- a/tests/test_formdata.py +++ b/tests/test_formdata.py @@ -1773,9 +1773,14 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data): tmpl = Template('{{form_objects|with_drafts|count}}') assert tmpl.render(context) == '12' - # test |filter_by_internal_id + # test |filter_by_internal_id & |filter_by_identifier context = pub.substitutions.get_context_variables(mode='lazy') - for tpl in ['filter_by_internal_id', 'filter_by:"internal_id"|filter_value']: + for tpl in [ + 'filter_by_internal_id', + 'filter_by:"internal_id"|filter_value', + 'filter_by_identifier', + 'filter_by:"identifier"|filter_value', + ]: pub.loggederror_class.wipe() tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, finished_formdata.id)) assert tmpl.render(context) == '1' @@ -1783,9 +1788,12 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data): assert tmpl.render(context) == '0' tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, 'invalid value')) assert tmpl.render(context) == '0' - assert pub.loggederror_class.count() == 1 - logged_error = pub.loggederror_class.select(order_by='id')[0] - assert logged_error.summary == 'Invalid value "invalid value" for filter "internal_id"' + if 'internal_id' in tpl: + assert pub.loggederror_class.count() == 1 + logged_error = pub.loggederror_class.select(order_by='id')[0] + assert logged_error.summary == 'Invalid value "invalid value" for filter "internal_id"' + elif 'identifier' in tpl: + assert pub.loggederror_class.count() == 0 pub.loggederror_class.wipe() queryset = lazy_formdata.objects.filter_by_internal_id(None) assert pub.loggederror_class.count() == 1 diff --git a/wcs/carddef.py b/wcs/carddef.py index 9d7a6e2d7..bfe4ff4b7 100644 --- a/wcs/carddef.py +++ b/wcs/carddef.py @@ -143,18 +143,6 @@ class CardDef(FormDef): self.roles = self.backoffice_submission_roles return super().store(comment=comment, *args, **kwargs) - def get_by_id_criteria(self, value): - if self.id_template: - return Equal('id_display', str(value)) - try: - if int(value) >= 2**31: - # out of range for postgresql integer type; would raise DataError. - raise OverflowError - except ValueError: - # value not an integer, it could be id_display - return Equal('id_display', str(value)) - return Equal('id', value) - @classmethod def get_carddefs_as_data_source(cls): carddefs_by_id = {} diff --git a/wcs/formdef.py b/wcs/formdef.py index 9c2876d60..9a69a7870 100644 --- a/wcs/formdef.py +++ b/wcs/formdef.py @@ -784,6 +784,18 @@ class FormDef(StorableObject): def get_display_id_format(self): return self.id_template or '{{formdef_id}}-{{form_number_raw}}' + def get_by_id_criteria(self, value): + if self.id_template: + return Equal('id_display', str(value)) + try: + if int(value) >= 2**31: + # out of range for postgresql integer type; would raise DataError. + raise OverflowError + except ValueError: + # value not an integer, it could be id_display + return Equal('id_display', str(value)) + return Equal('id', value) + def get_submission_lateral_block(self): context = get_publisher().substitutions.get_context_variables(mode='lazy') if self.submission_lateral_template is None: diff --git a/wcs/qommon/templatetags/qommon.py b/wcs/qommon/templatetags/qommon.py index c966d6c73..854099016 100644 --- a/wcs/qommon/templatetags/qommon.py +++ b/wcs/qommon/templatetags/qommon.py @@ -802,6 +802,11 @@ def filter_by_number(queryset, form_number): return queryset.filter_by_number(form_number) +@register_queryset_filter +def filter_by_identifier(queryset, form_identifier): + return queryset.filter_by_identifier(form_identifier) + + @register_queryset_filter def pending(queryset): return queryset.pending() diff --git a/wcs/variables.py b/wcs/variables.py index 1e00fd657..b829763be 100644 --- a/wcs/variables.py +++ b/wcs/variables.py @@ -255,12 +255,19 @@ class LazyFormDefObjectsManager: def filter_by_number(self, value, op='eq'): if op not in ['eq']: self.report_error( - _('Invalid operator "%(op)s" for filter "%(filter)s"') - % {'op': self.get_operator_name(op), 'filter': self.pending_attr}, + _('Invalid operator "%(op)s" for filter "number"') % {'op': self.get_operator_name(op)} ) return self.none() return self._clone(self._criterias + [Equal('id_display', str(value))]) + def filter_by_identifier(self, value, op='eq'): + if op not in ['eq']: + self.report_error( + _('Invalid operator "%(op)s" for filter "identifier"') % {'op': self.get_operator_name(op)} + ) + return self.none() + return self._clone(self._criterias + [self._formdef.get_by_id_criteria(str(value))]) + def get_fields(self, key): for field in self._formdef.iter_fields(include_block_fields=True): if getattr(field, 'block_field', None): @@ -468,7 +475,7 @@ class LazyFormDefObjectsManager: self.report_error(_('|filter_value called without attribute (check |filter_by parameter)')) return self.none() op = 'ne' if exclude else getattr(self, 'pending_op', 'eq') - if self.pending_attr in ['status', 'user', 'internal_id', 'number', 'distance']: + if self.pending_attr in ['status', 'user', 'internal_id', 'number', 'distance', 'identifier']: return getattr(self, 'filter_by_%s' % self.pending_attr)(value, op) fields = list(self.get_fields(self.pending_attr))