Extend Django-import-export's Import Form To Specify Fixed Value For Each Imported Row
Solution 1:
EDIT(2): Solved through the use of sessions. Having a get_confirm_import_form
hook would still really help here, but even better would be having the existing ConfirmImportForm
carry across all the submitted fields & values from the initial import form.
EDIT: I'm sorry, I thought I had this nailed, but my own code wasn't working as well as I thought it was. This doesn't solve the problem of passing along the sector
form field in the ConfirmImportForm
, which is necessary for the import to complete. Currently looking for a solution which doesn't involve pasting the whole of import_action()
into an ImportMixin
subclass. Having a get_confirm_import_form()
hook would help a lot here.
Still working on a solution for myself, and when I have one I'll update this too.
Don't override import_action
. It's a big complicated method that you don't want to replicate. More importantly, as I discovered today: there are easier ways of doing this.
First (as you mentioned), make a custom import form for Location
that allows the user to choose a Sector
:
classLocationImportForm(ImportForm):
sector = forms.ModelChoiceField(required=True, queryset=Sector.objects.all())
In the Resource API, there's a before_import_row()
hook that is called once per row. So, implement that in your LocationResource
class, and use it to add the Sector
column:
defbefore_import_row(self, row, **kwargs):
sector = self.request.POST.get('sector', None)
if contract:
self.request.session['import_context_sector'] = sector
else:
# if this raises a KeyError, we want to know about it.# It means that we got to a point of importing data without# contract context, and we don't want to continue.try:
sector = self.request.session['import_context_sector']
except KeyError as e:
raise Exception("Sector context failure on row import, " +
f"check resources.py for more info: {e}")
row['sector'] = sector
(Note: This code uses Django sessions to carry the sector
value from the import form to the import confirmation screen. If you're not using sessions, you'll need to find another way to do it.)
This is all you need to get the extra data in, and it works for both the dry-run preview and the actual import.
Note that self.request
doesn't exist in the default ModelResource
- we have to install it by giving LocationResource
a custom constructor:
def__init__(self, request=None):
super()
self.request = request
(Don't worry about self.request
sticking around. Each LocationResource
instance doesn't persist beyond a single request.)
The request
isn't usually passed to the ModelResource
constructor, so we need to add it to the kwargs dict for that call. Fortunately, Django Import/Export has a dedicated hook for that. Override ImportExportModelAdmin
's get_resource_kwargs
method in LocationAdmin
:
defget_resource_kwargs(self, request, *args, **kwargs):
rk = super().get_resource_kwargs(request, *args, **kwargs)
rk['request'] = request
return rk
And that's all you need.
Post a Comment for "Extend Django-import-export's Import Form To Specify Fixed Value For Each Imported Row"