diff --git a/src/backend/InvenTree/InvenTree/serializers.py b/src/backend/InvenTree/InvenTree/serializers.py index 14c24de598..e6a639debd 100644 --- a/src/backend/InvenTree/InvenTree/serializers.py +++ b/src/backend/InvenTree/InvenTree/serializers.py @@ -49,7 +49,10 @@ class FilterableSerializerField: def enable_filter( - func: Any, default_include: bool = False, filter_name: Optional[str] = None + func: Any, + default_include: bool = False, + filter_name: Optional[str] = None, + filter_by_query: bool = True, ): """Decorator for marking a serializer field as filterable. @@ -59,6 +62,10 @@ def enable_filter( func: The serializer field to mark as filterable. Will automatically be passed when used as a decorator. default_include (bool): If True, the field will be included by default unless explicitly excluded. If False, the field will be excluded by default unless explicitly included. filter_name (str, optional): The name of the filter parameter to use in the URL. If None, the function name of the (decorated) function will be used. + filter_by_query (bool): If True, also look for filter parameters in the request query parameters. + + Returns: + The decorated serializer field, marked as filterable. """ # Ensure this function can be actually filteres if not issubclass(func.__class__, FilterableSerializerField): @@ -71,6 +78,7 @@ def enable_filter( func._kwargs['is_filterable_vals'] = { 'default': default_include, 'filter_name': filter_name if filter_name else func.field_name, + 'filter_by_query': filter_by_query, } return func @@ -129,7 +137,7 @@ class FilterableSerializerMixin: val = kwargs.pop(pop_ref, poped_kwargs.get(pop_ref)) # Optionally also look in query parameters - if val is None and self.filter_on_query: + if val is None and self.filter_on_query and v.get('filter_by_query', True): val = query_params.pop(pop_ref, None) if isinstance(val, list) and len(val) == 1: val = val[0] diff --git a/src/backend/InvenTree/InvenTree/test_serializers.py b/src/backend/InvenTree/InvenTree/test_serializers.py index 9fc5babd6e..0436083fef 100644 --- a/src/backend/InvenTree/InvenTree/test_serializers.py +++ b/src/backend/InvenTree/InvenTree/test_serializers.py @@ -22,7 +22,7 @@ class SampleSerializer( """Meta options.""" model = User - fields = ['field_a', 'field_b', 'field_c', 'field_d', 'id'] + fields = ['field_a', 'field_b', 'field_c', 'field_d', 'field_e', 'id'] field_a = SerializerMethodField(method_name='sample') field_b = InvenTree.serializers.enable_filter( @@ -38,6 +38,11 @@ class SampleSerializer( True, filter_name='crazy_name', ) + field_e = InvenTree.serializers.enable_filter( + InvenTree.serializers.FilterableSerializerMethodField(method_name='sample'), + filter_name='field_e', + filter_by_query=False, + ) def sample(self, obj): """Sample method field.""" @@ -94,6 +99,14 @@ class FilteredSerializers(InvenTreeAPITestCase): self.assertNotContains(response, 'field_c') self.assertNotContains(response, 'field_d') + # Query parameters being turned off means it should not be enable-able + response = self.client.get(url, {'field_e': True}) + self.assertContains(response, 'field_a') + self.assertNotContains(response, 'field_b') + self.assertContains(response, 'field_c') + self.assertContains(response, 'field_d') + self.assertNotContains(response, 'field_e') + def test_failiure_enable_filter(self): """Test sanity check for enable_filter.""" # Allowed usage