Repository: django-import-export/django-import-export

Issue:
cannot exclude id field during import : KeyError: u'id'
am trying to import in admin and already excluded the id field but i get

```
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/import_export/resources.py", line 434, in import_row
instance, new = self.get_or_init_instance(instance_loader, row)
File "/usr/local/lib/python2.7/dist-packages/import_export/resources.py", line 258, in get_or_init_instance
instance = self.get_instance(instance_loader, row)
File "/usr/local/lib/python2.7/dist-packages/import_export/resources.py", line 252, in get_instance
return instance_loader.get_instance(row)
File "/usr/local/lib/python2.7/dist-packages/import_export/instance_loaders.py", line 31, in get_instance
field = self.resource.fields[key]
KeyError: u'id'
```

why is it compulsory to include id field i thought it should be autogenerated


Discussion:
i'm having the same issue, it seems like the meta class option import_id_fields doesn't work when you give it a new value. it still using the default one 'id'. 

eventually, i have to change the xls file to add a column 'id' in header then import works 

```
class SponsorBlockResource(resources.ModelResource):
  class Meta:
        model = SponsorBlock
        exclude = ('id', )
        import_id_fields = ('name',)
        skip_unchanged = True
        fields = ['name','block_time',]
```
yes that's what i did to fix the problem but i think its not necessary to include id field when importing new data, a fix for this in the package would be nice.
@jwzh222  Where did you add this SponsorBlockResource class in Django admin.py or views.py or someother file?
Please specify
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/import_export/resources.py b/import_export/resources.py
--- a/import_export/resources.py
+++ b/import_export/resources.py
@@ -252,8 +252,13 @@ def init_instance(self, row=None):
 
     def get_instance(self, instance_loader, row):
         """
-        Calls the :doc:`InstanceLoader <api_instance_loaders>`.
+        If all 'import_id_fields' are present in the dataset, calls
+        the :doc:`InstanceLoader <api_instance_loaders>`. Otherwise,
+        returns `None`.
         """
+        for field_name in self.get_import_id_fields():
+            if field_name not in row:
+                return
         return instance_loader.get_instance(row)
 
     def get_or_init_instance(self, instance_loader, row):


Test patch:
diff --git a/tests/core/tests/test_resources.py b/tests/core/tests/test_resources.py
--- a/tests/core/tests/test_resources.py
+++ b/tests/core/tests/test_resources.py
@@ -4,7 +4,7 @@
 from copy import deepcopy
 from datetime import date
 from decimal import Decimal
-from unittest import skip, skipUnless
+from unittest import mock, skip, skipUnless
 
 from django.conf import settings
 from django.contrib.auth.models import User
@@ -253,17 +253,33 @@ class Meta:
         instance = resource.get_instance(instance_loader, self.dataset.dict[0])
         self.assertEqual(instance, self.book)
 
-    def test_get_instance_with_missing_field_data(self):
+    def test_get_instance_usually_defers_to_instance_loader(self):
+        self.resource._meta.import_id_fields = ['id']
+
         instance_loader = self.resource._meta.instance_loader_class(
             self.resource)
+
+        with mock.patch.object(instance_loader, 'get_instance') as mocked_method:
+            row = self.dataset.dict[0]
+            self.resource.get_instance(instance_loader, row)
+            # instance_loader.get_instance() should have been called
+            mocked_method.assert_called_once_with(row)
+
+    def test_get_instance_when_id_fields_not_in_dataset(self):
+        self.resource._meta.import_id_fields = ['id']
+
         # construct a dataset with a missing "id" column
         dataset = tablib.Dataset(headers=['name', 'author_email', 'price'])
         dataset.append(['Some book', 'test@example.com', "10.25"])
-        with self.assertRaises(KeyError) as cm:
-            self.resource.get_instance(instance_loader, dataset.dict[0])
-        self.assertEqual("Column 'id' not found in dataset. Available columns "
-                         "are: %s" % ['name', 'author_email', 'price'],
-                         cm.exception.args[0])
+
+        instance_loader = self.resource._meta.instance_loader_class(self.resource)
+
+        with mock.patch.object(instance_loader, 'get_instance') as mocked_method:
+            result = self.resource.get_instance(instance_loader, dataset.dict[0])
+            # Resource.get_instance() should return None
+            self.assertIs(result, None)
+            # instance_loader.get_instance() should NOT have been called
+            mocked_method.assert_not_called()
 
     def test_get_export_headers(self):
         headers = self.resource.get_export_headers()