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

1"""Mixin classes for data import/export functionality.""" 

2 

3from rest_framework import fields, serializers 

4from taggit.serializers import TagListSerializerField 

5 

6 

7class DataImportSerializerMixin: 

8 """Mixin class for adding data import functionality to a DRF serializer.""" 

9 

10 import_only_fields = [] 

11 import_exclude_fields = [] 

12 

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 

16 

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 

20 

21 def __init__(self, *args, **kwargs): 

22 """Initialise the DataImportSerializerMixin. 

23 

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) 

28 

29 super().__init__(*args, **kwargs) 

30 

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()) 

35 

36 for field in field_names: 

37 if field not in importable_field_names: 

38 self.fields.pop(field, None) 

39 

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) 

43 

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) 

48 

49 def get_importable_fields(self) -> dict: 

50 """Return a dict of fields which can be imported against this serializer instance. 

51 

52 Returns: 

53 dict: A dictionary of field names and field objects 

54 """ 

55 importable_fields = {} 

56 

57 if meta := getattr(self, 'Meta', None): 

58 read_only_fields = getattr(meta, 'read_only_fields', []) 

59 else: 

60 read_only_fields = [] 

61 

62 for name, field in self.fields.items(): 

63 # Skip read-only fields 

64 if getattr(field, 'read_only', False): 

65 continue 

66 

67 if name in read_only_fields: 

68 continue 

69 

70 # Skip fields which are themselves serializers 

71 if issubclass(field.__class__, serializers.Serializer): 

72 continue 

73 

74 # Skip file fields 

75 if issubclass(field.__class__, fields.FileField): 

76 continue 

77 

78 # Skip tags fields 

79 # TODO: Implement tag field import support 

80 if issubclass(field.__class__, TagListSerializerField): 

81 continue 

82 

83 importable_fields[name] = field 

84 

85 return importable_fields