2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-10-25 02:17:37 +00:00
This commit is contained in:
Matthias Mair
2025-10-05 21:34:30 +02:00
parent 3ee3cea8d8
commit 47892e409e
2 changed files with 49 additions and 12 deletions

View File

@@ -14,6 +14,7 @@ from InvenTree.helpers import (
strip_html_tags, strip_html_tags,
) )
from InvenTree.schema import schema_for_view_output_options from InvenTree.schema import schema_for_view_output_options
from InvenTree.serializers import OptionalFilterabelSerializer
class CleanMixin: class CleanMixin:
@@ -203,6 +204,7 @@ class UpdateAPI(CleanMixin, generics.UpdateAPIView):
class DataImportExportSerializerMixin( class DataImportExportSerializerMixin(
OptionalFilterabelSerializer,
data_exporter.mixins.DataExportSerializerMixin, data_exporter.mixins.DataExportSerializerMixin,
importer.mixins.DataImportSerializerMixin, importer.mixins.DataImportSerializerMixin,
): ):

View File

@@ -29,7 +29,7 @@ from InvenTree.fields import InvenTreeRestURLField, InvenTreeURLField
# region path filtering # region path filtering
class OptionalFilterabelSerializer(serializers.Serializer): class OptionalFilterabelSerializer:
"""Mixin to add context to serializer.""" """Mixin to add context to serializer."""
is_filterable = None is_filterable = None
@@ -37,28 +37,53 @@ class OptionalFilterabelSerializer(serializers.Serializer):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Initialize the serializer.""" """Initialize the serializer."""
self.is_filterable = kwargs.pop('is_filterable', None) if self.is_filterable is None:
self.is_filterable_default = kwargs.pop('is_filterable_default', True) self.is_filterable = kwargs.pop('is_filterable', None)
self.is_filterable_default = kwargs.pop('is_filterable_default', True)
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
class PathScopedMixin: class FractionalFilterabelSerializer:
"""A."""
def __init__(self, *args, **kwargs):
"""Add detail fields."""
kwargs = PathScopedMixin.gather_filters(self, kwargs)
super().__init__(*args, **kwargs)
PathScopedMixin.do_filtering(self, *args, **kwargs)
class PathScopedMixin(serializers.Serializer):
"""Mixin to disable a serializer field based on kwargs passed to the view.""" """Mixin to disable a serializer field based on kwargs passed to the view."""
no_filter = False
_was_filtered = False
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer.""" """Initialization routine for the serializer."""
flt_fld = { self.gather_filters(kwargs)
k: a for k, a in self.fields.items() if getattr(a, 'is_filterable', None)
}
filter_targets = {k: kwargs.pop(k, False) for k in flt_fld}
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.do_filtering(*args, **kwargs)
if InvenTree.ready.isGeneratingSchema(): def gather_filters(self, kwargs):
"""Gather filterable fields."""
if getattr(self, '_was_filtered', False):
return kwargs
self._was_filtered = True
# Actually gather the filterable fields
fields = self.fields.items()
flt_fld = {k: a for k, a in fields if getattr(a, 'is_filterable', None)}
self.filter_targets = {k: kwargs.pop(k, False) for k in flt_fld}
return kwargs
def do_filtering(self, *args, **kwargs):
"""Do the actual filtering."""
if InvenTree.ready.isGeneratingSchema() or not hasattr(self, 'filter_targets'):
return return
# Throw out fields which are not requested # Throw out fields which are not requested
for k, v in filter_targets.items(): for k, v in self.filter_targets.items():
if v is not True: if v is not True:
self.fields.pop(k, None) self.fields.pop(k, None)
@@ -66,6 +91,14 @@ class PathScopedMixin:
# Decorator for marking serialzier fields that can be filtered out # Decorator for marking serialzier fields that can be filtered out
def can_filter(func, default=False): def can_filter(func, default=False):
"""Decorator for marking serializer fields as filterable.""" """Decorator for marking serializer fields as filterable."""
# Check if function is holding OptionalFilterabelSerializer somehow
if not issubclass(func.__class__, OptionalFilterabelSerializer):
return
if not isinstance(func, OptionalFilterabelSerializer):
return
# raise TypeError('can_filter can only be applied to OptionalFilterabelSerializer Serializers!')
if isinstance(func, serializers.ListSerializer):
return func
func._kwargs['is_filterable'] = True func._kwargs['is_filterable'] = True
func._kwargs['is_filterable_default'] = default func._kwargs['is_filterable_default'] = default
return func return func
@@ -269,7 +302,9 @@ class DependentField(serializers.Field):
class InvenTreeModelSerializer( class InvenTreeModelSerializer(
OptionalFilterabelSerializer, serializers.ModelSerializer FractionalFilterabelSerializer,
OptionalFilterabelSerializer,
serializers.ModelSerializer,
): ):
"""Inherits the standard Django ModelSerializer class, but also ensures that the underlying model class data are checked on validation.""" """Inherits the standard Django ModelSerializer class, but also ensures that the underlying model class data are checked on validation."""