Coverage for src/backend/InvenTree/importer/mixins.py: 25%
40 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""Mixin classes for data import/export functionality."""
3from rest_framework import fields, serializers
4from taggit.serializers import TagListSerializerField
7class DataImportSerializerMixin:
8 """Mixin class for adding data import functionality to a DRF serializer."""
10 import_only_fields = []
11 import_exclude_fields = []
13 def get_import_only_fields(self, **kwargs) -> list:
14 """Return the list of field names which are only used during data import."""
15 return self.import_only_fields
17 def get_import_exclude_fields(self, **kwargs) -> list:
18 """Return the list of field names which are excluded during data import."""
19 return self.import_exclude_fields
21 def __init__(self, *args, **kwargs):
22 """Initialise the DataImportSerializerMixin.
24 Determine if the serializer is being used for data import,
25 and if so, adjust the serializer fields accordingly.
26 """
27 self._is_importing = kwargs.pop('importing', False)
29 super().__init__(*args, **kwargs)
31 if self._is_importing: 31 ↛ 33line 31 didn't jump to line 33 because the condition on line 31 was never true
32 # Exclude any fields which are not able to be imported
33 importable_field_names = list(self.get_importable_fields().keys())
34 field_names = list(self.fields.keys())
36 for field in field_names:
37 if field not in importable_field_names:
38 self.fields.pop(field, None)
40 # Exclude fields which are excluded for data import
41 for field in self.get_import_exclude_fields(**kwargs):
42 self.fields.pop(field, None)
44 else:
45 # Exclude fields which are only used for data import
46 for field in self.get_import_only_fields(**kwargs): 46 ↛ 47line 46 didn't jump to line 47 because the loop on line 46 never started
47 self.fields.pop(field, None)
49 def get_importable_fields(self) -> dict:
50 """Return a dict of fields which can be imported against this serializer instance.
52 Returns:
53 dict: A dictionary of field names and field objects
54 """
55 importable_fields = {}
57 if meta := getattr(self, 'Meta', None):
58 read_only_fields = getattr(meta, 'read_only_fields', [])
59 else:
60 read_only_fields = []
62 for name, field in self.fields.items():
63 # Skip read-only fields
64 if getattr(field, 'read_only', False):
65 continue
67 if name in read_only_fields:
68 continue
70 # Skip fields which are themselves serializers
71 if issubclass(field.__class__, serializers.Serializer):
72 continue
74 # Skip file fields
75 if issubclass(field.__class__, fields.FileField):
76 continue
78 # Skip tags fields
79 # TODO: Implement tag field import support
80 if issubclass(field.__class__, TagListSerializerField):
81 continue
83 importable_fields[name] = field
85 return importable_fields