Reputation: 45
I am using import-export library and trying to add import functionality in admin panel.
Resource:
class DictCitizen_FisResources(resources.ModelResource):
id = fields.Field(
column_name='№',
attribute='id',
)
country_name = fields.Field(
column_name='Name',
attribute='dict_citizen',
widget=ForeignKeyWidget(DictCitizen, field='sname')
)
fis_id = fields.Field(
column_name='Element Code',
attribute='fis_id',
)
class Meta:
model = DictCitizen_Fis
fields = ('id','country_name', 'fis_id',)
import_id_fields = ('id',)
As u can see, one of the fields in ResourceClass (country_name) has ForeignKeyWidget, which means that when importing data from file - model relation is going to be created. The problem is that, information in the file that i import from, does not always matches ForeignKeyWidget model data that is already in database and as a result i get next errors when trying to imoprt from admin panel:
Same error written as a text:
Номер строки: 25 - DictCitizen matching query does not exist. 25, БОЛИВИЯ, 238 Traceback (most recent call last): File "C:\venvs\abit\lib\site-packages\import_export\resources.py", line 737, in import_row self.import_obj(instance, row, dry_run, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\resources.py", line 557, in import_obj self.import_field(field, obj, data, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\resources.py", line 540, in import_field field.save(obj, data, is_m2m, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\fields.py", line 119, in save cleaned = self.clean(data, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\fields.py", line 75, in clean value = self.widget.clean(value, row=data, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\widgets.py", line 423, in clean return self.get_queryset(value, row, kwargs).get({self.field: val}) File "C:\venvs\abit\lib\site-packages\django\db\models\query.py", line 496, in get raise self.model.DoesNotExist( dicts.models.base.DictCitizen.DoesNotExist: DictCitizen matching query does not exist
.
Номер строки: 36 - DictCitizen matching query does not exist. 36, ВЕНЕСУЭЛА, 228 Traceback (most recent call last): File "C:\venvs\abit\lib\site-packages\import_export\resources.py", line 737, in import_row self.import_obj(instance, row, dry_run, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\resources.py", line 557, in import_obj self.import_field(field, obj, data, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\resources.py", line 540, in import_field field.save(obj, data, is_m2m, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\fields.py", line 119, in save cleaned = self.clean(data, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\fields.py", line 75, in clean value = self.widget.clean(value, row=data, **kwargs) File "C:\venvs\abit\lib\site-packages\import_export\widgets.py", line 423, in clean return self.get_queryset(value, row, kwargs).get({self.field: val}) File "C:\venvs\abit\lib\site-packages\django\db\models\query.py", line 496, in get raise self.model.DoesNotExist( dicts.models.base.DictCitizen.DoesNotExist: DictCitizen matching query does not exist.
Because there are certain rows in the file, that contain information that does not match related model data, none of the rows are getting imported and i get error.
I would like to know how can i handle this kind of exeptions in the way so that all the matching row instances would be saved (imoprted) in database, and i could log the information about those that cannot be saved since related model cannot be found due to the DoesNotExist exeption.
Upvotes: 0
Views: 429
Reputation: 4231
The best way would be to create a subclass of ForeignKeyWidget
which ignores any failures (or you can log them or whatever):
class PermissiveForeignKeyWidget(ForeignKeyWidget):
def clean(self, value, row=None, **kwargs):
try:
return super().clean(value)
except self.model.DoesNotExist:
logger.warning(f"instance matching '{value}' does not exist")
Then declare this in your resource:
country_name = fields.Field(
column_name='Name',
attribute='dict_citizen',
widget=PermissiveForeignKeyWidget(DictCitizen, field='sname')
)
Upvotes: 2