Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/import_export/fields.py: 27%

72 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1from django.core.exceptions import ObjectDoesNotExist 

2from django.db.models.fields import NOT_PROVIDED 

3from django.db.models.manager import Manager 

4 

5from . import widgets 

6from .exceptions import FieldError 

7 

8 

9class Field: 

10 """ 

11 Field represent mapping between `object` field and representation of 

12 this field. 

13 

14 :param attribute: A string of either an instance attribute or callable off 

15 the object. 

16 

17 :param column_name: Lets you provide a name for the column that represents 

18 this field in the export. 

19 

20 :param widget: Defines a widget that will be used to represent this 

21 field's data in the export, or transform the value during import. 

22 

23 :param readonly: A Boolean which defines if this field will be ignored 

24 during import. 

25 

26 :param default: This value will be returned by 

27 :meth:`~import_export.fields.Field.clean` if this field's widget did 

28 not return an adequate value. 

29 

30 :param saves_null_values: Controls whether null values are saved on the object 

31 :param dehydrate_method: Lets you choose your own method for dehydration rather 

32 than using `dehydrate_{field_name}` syntax. 

33 :param m2m_add: changes save of this field to add the values, if they do not exist, 

34 to a ManyToMany field instead of setting all values. Only useful if field is 

35 a ManyToMany field. 

36 """ 

37 empty_values = [None, ''] 

38 

39 def __init__(self, attribute=None, column_name=None, widget=None, 

40 default=NOT_PROVIDED, readonly=False, saves_null_values=True, 

41 dehydrate_method=None, m2m_add=False): 

42 self.attribute = attribute 

43 self.default = default 

44 self.column_name = column_name 

45 if not widget: 

46 widget = widgets.Widget() 

47 self.widget = widget 

48 self.readonly = readonly 

49 self.saves_null_values = saves_null_values 

50 self.dehydrate_method = dehydrate_method 

51 self.m2m_add = m2m_add 

52 

53 def __repr__(self): 

54 """ 

55 Displays the module, class and name of the field. 

56 """ 

57 path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__) 

58 column_name = getattr(self, 'column_name', None) 

59 if column_name is not None: 

60 return '<%s: %s>' % (path, column_name) 

61 return '<%s>' % path 

62 

63 def clean(self, data, **kwargs): 

64 """ 

65 Translates the value stored in the imported datasource to an 

66 appropriate Python object and returns it. 

67 """ 

68 try: 

69 value = data[self.column_name] 

70 except KeyError: 

71 raise KeyError("Column '%s' not found in dataset. Available " 

72 "columns are: %s" % (self.column_name, list(data))) 

73 

74 # If ValueError is raised here, import_obj() will handle it 

75 value = self.widget.clean(value, row=data, **kwargs) 

76 

77 if value in self.empty_values and self.default != NOT_PROVIDED: 

78 if callable(self.default): 

79 return self.default() 

80 return self.default 

81 

82 return value 

83 

84 def get_value(self, obj): 

85 """ 

86 Returns the value of the object's attribute. 

87 """ 

88 if self.attribute is None: 

89 return None 

90 

91 attrs = self.attribute.split('__') 

92 value = obj 

93 

94 for attr in attrs: 

95 try: 

96 value = getattr(value, attr, None) 

97 except (ValueError, ObjectDoesNotExist): 

98 # needs to have a primary key value before a many-to-many 

99 # relationship can be used. 

100 return None 

101 if value is None: 

102 return None 

103 

104 # RelatedManager and ManyRelatedManager classes are callable in 

105 # Django >= 1.7 but we don't want to call them 

106 if callable(value) and not isinstance(value, Manager): 

107 value = value() 

108 return value 

109 

110 def save(self, obj, data, is_m2m=False, **kwargs): 

111 """ 

112 If this field is not declared readonly, the object's attribute will 

113 be set to the value returned by :meth:`~import_export.fields.Field.clean`. 

114 """ 

115 if not self.readonly: 

116 attrs = self.attribute.split('__') 

117 for attr in attrs[:-1]: 

118 obj = getattr(obj, attr, None) 

119 cleaned = self.clean(data, **kwargs) 

120 if cleaned is not None or self.saves_null_values: 

121 if not is_m2m: 

122 setattr(obj, attrs[-1], cleaned) 

123 else: 

124 if self.m2m_add: 

125 getattr(obj, attrs[-1]).add(*cleaned) 

126 else: 

127 getattr(obj, attrs[-1]).set(cleaned) 

128 

129 def export(self, obj): 

130 """ 

131 Returns value from the provided object converted to export 

132 representation. 

133 """ 

134 value = self.get_value(obj) 

135 if value is None: 

136 return "" 

137 return self.widget.render(value, obj) 

138 

139 def get_dehydrate_method(self, field_name=None): 

140 """ 

141 Returns method name to be used for dehydration of the field. 

142 Defaults to `dehydrate_{field_name}` 

143 """ 

144 DEFAULT_DEHYDRATE_METHOD_PREFIX = "dehydrate_" 

145 

146 if not self.dehydrate_method and not field_name: 

147 raise FieldError("Both dehydrate_method and field_name are not supplied.") 

148 

149 return self.dehydrate_method or DEFAULT_DEHYDRATE_METHOD_PREFIX + field_name