Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add kwargs to import_row, import_object and import_field #1190

Merged
merged 6 commits into from
Jul 12, 2021
8 changes: 4 additions & 4 deletions import_export/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __repr__(self):
return '<%s: %s>' % (path, column_name)
return '<%s>' % path

def clean(self, data):
def clean(self, data, **kwargs):
"""
Translates the value stored in the imported datasource to an
appropriate Python object and returns it.
Expand All @@ -63,7 +63,7 @@ def clean(self, data):
"columns are: %s" % (self.column_name, list(data)))

# If ValueError is raised here, import_obj() will handle it
value = self.widget.clean(value, row=data)
value = self.widget.clean(value, row=data, **kwargs)

if value in self.empty_values and self.default != NOT_PROVIDED:
if callable(self.default):
Expand Down Expand Up @@ -98,7 +98,7 @@ def get_value(self, obj):
value = value()
return value

def save(self, obj, data, is_m2m=False):
def save(self, obj, data, is_m2m=False, **kwargs):
"""
If this field is not declared readonly, the object's attribute will
be set to the value returned by :meth:`~import_export.fields.Field.clean`.
Expand All @@ -107,7 +107,7 @@ def save(self, obj, data, is_m2m=False):
attrs = self.attribute.split('__')
for attr in attrs[:-1]:
obj = getattr(obj, attr, None)
cleaned = self.clean(data)
cleaned = self.clean(data, **kwargs)
if cleaned is not None or self.saves_null_values:
if not is_m2m:
setattr(obj, attrs[-1], cleaned)
Expand Down
10 changes: 5 additions & 5 deletions import_export/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,18 +490,18 @@ def after_delete_instance(self, instance, dry_run):
"""
pass

def import_field(self, field, obj, data, is_m2m=False):
def import_field(self, field, obj, data, is_m2m=False, **kwargs):
"""
Calls :meth:`import_export.fields.Field.save` if ``Field.attribute``
and ``Field.column_name`` are found in ``data``.
"""
if field.attribute and field.column_name in data:
field.save(obj, data, is_m2m)
field.save(obj, data, is_m2m, **kwargs)

def get_import_fields(self):
return self.get_fields()

def import_obj(self, obj, data, dry_run):
def import_obj(self, obj, data, dry_run, **kwargs):
"""
Traverses every field in this Resource and calls
:meth:`~import_export.resources.Resource.import_field`. If
Expand All @@ -513,7 +513,7 @@ def import_obj(self, obj, data, dry_run):
if isinstance(field.widget, widgets.ManyToManyWidget):
continue
try:
self.import_field(field, obj, data)
self.import_field(field, obj, data, **kwargs)
except ValueError as e:
errors[field.attribute] = ValidationError(
force_str(e), code="invalid")
Expand Down Expand Up @@ -659,7 +659,7 @@ def import_row(self, row, instance_loader, using_transactions=True, dry_run=Fals
else:
import_validation_errors = {}
try:
self.import_obj(instance, row, dry_run)
self.import_obj(instance, row, dry_run, **kwargs)
except ValidationError as e:
# Validation errors from import_obj() are passed on to
# validate_instance(), where they can be combined with model
Expand Down
4 changes: 2 additions & 2 deletions tests/core/tests/test_admin_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,9 @@ def decorator(func):
# Cause an exception in import_row, but only after import is confirmed,
# so a failure only occurs when ImportMixin.process_import is called.
class R(BookResource):
def import_obj(self, obj, data, dry_run):
def import_obj(self, obj, data, dry_run, **kwargs):
if dry_run:
super().import_obj(obj, data, dry_run)
super().import_obj(obj, data, dry_run, **kwargs)
else:
raise Exception

Expand Down