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
« 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
5from . import widgets
6from .exceptions import FieldError
9class Field:
10 """
11 Field represent mapping between `object` field and representation of
12 this field.
14 :param attribute: A string of either an instance attribute or callable off
15 the object.
17 :param column_name: Lets you provide a name for the column that represents
18 this field in the export.
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.
23 :param readonly: A Boolean which defines if this field will be ignored
24 during import.
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.
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, '']
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
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
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)))
74 # If ValueError is raised here, import_obj() will handle it
75 value = self.widget.clean(value, row=data, **kwargs)
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
82 return value
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
91 attrs = self.attribute.split('__')
92 value = obj
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
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
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)
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)
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_"
146 if not self.dehydrate_method and not field_name:
147 raise FieldError("Both dehydrate_method and field_name are not supplied.")
149 return self.dehydrate_method or DEFAULT_DEHYDRATE_METHOD_PREFIX + field_name