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

Issue:
Importing an xlsx file with no headers shows a blank screen
**Describe the bug**

If you import a file with no headers via the Admin Console then there is no error message to the user, instead a blank confirm screen is shown and the import has no effect.

It would perhaps be better to show a valid warning message about no headers being present.

**To Reproduce**

Import the attached book file via the Admin Console (Import Book)

[books no headers.xlsx](https://github.com/django-import-export/django-import-export/files/11171750/books.no.headers.xlsx)

**Versions (please complete the following information):**
 - Django Import Export: 3.1.0
 - Python 3.10
 - Django 4.1.7

**Expected behavior**

A warning message is shown that there is no valid data to import

**Screenshots**


![Screenshot 2023-04-06 at 15 41 37](https://user-images.githubusercontent.com/6249838/230415002-23782706-e23e-4be1-b24d-fb2675862948.png)

![Screenshot 2023-04-06 at 15 44 50](https://user-images.githubusercontent.com/6249838/230415186-426bead5-93a2-4d8d-80f0-3ff847141c55.png)



Discussion:
@matthewhegarty You can assign me this
Thanks Eric - please can you take a branch off `release-4` - then this can go into v4
> Thanks Eric - please can you take a branch off `release-4` - then this can go into v4

Okay
Hi Eric - this could go into release-4 if you are able to complete it soon
Hello. I'll look into it this weekend.

On Thu, 11 Jan 2024 at 22:37, Matt Hegarty ***@***.***> wrote:

> Hi Eric - this could go into release-4 if you are able to complete it soon
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/django-import-export/django-import-export/issues/1569#issuecomment-1887842146>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AH4HSZCBHSCXYIIEF23NGXTYOA5PZAVCNFSM6AAAAAAWVQG5ASVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBXHA2DEMJUGY>
> .
> You are receiving this because you were assigned.Message ID:
> ***@***.***
> com>
>


-- 
*Work hard and smart Anywhere with the resources you have.*

Hi Eric, just to let you know that I am planning release 4 in around 4 weeks time.  No pressure, but if you would like this change to go into v4, then please submit as soon as you can.


Resolving patch:
diff --git a/import_export/admin.py b/import_export/admin.py
--- a/import_export/admin.py
+++ b/import_export/admin.py
@@ -489,6 +489,15 @@ def import_action(self, request, *args, **kwargs):
                     dataset = input_format.create_dataset(data)
                 except Exception as e:
                     self.add_data_read_fail_error_to_form(import_form, e)
+                else:
+                    if len(dataset) == 0:
+                        import_form.add_error(
+                            "import_file",
+                            _(
+                                "No valid data to import. Ensure your file "
+                                "has the correct headers or data for import."
+                            ),
+                        )
 
                 if not import_form.errors:
                     # prepare kwargs for import data, if needed


Test patch:
diff --git a/tests/core/exports/books-no-headers.csv b/tests/core/exports/books-no-headers.csv
new file mode 100644
--- /dev/null
+++ b/tests/core/exports/books-no-headers.csv
@@ -0,0 +1 @@
+abc
diff --git a/tests/core/tests/admin_integration/test_import.py b/tests/core/tests/admin_integration/test_import.py
--- a/tests/core/tests/admin_integration/test_import.py
+++ b/tests/core/tests/admin_integration/test_import.py
@@ -241,6 +241,36 @@ def test_import_action_handles_ValueError_as_form_error_with_translation(self):
         else:
             self.assertFormError(response, "form", "import_file", target_msg)
 
+    def test_import_action_invalidates_data_sheet_with_no_headers_or_data(self):
+        # GET the import form
+        response = self.client.get(self.book_import_url)
+        self.assertEqual(response.status_code, 200)
+        self.assertTemplateUsed(response, "admin/import_export/import.html")
+        self.assertContains(response, 'form action=""')
+
+        response = self._do_import_post(
+            self.book_import_url, "books-no-headers.csv", input_format=0
+        )
+        self.assertEqual(response.status_code, 200)
+        target_msg = (
+            "No valid data to import. Ensure your file "
+            "has the correct headers or data for import."
+        )
+
+        # required for testing via tox
+        # remove after django 5.0 released
+        if django.VERSION >= (4, 0):
+            with warnings.catch_warnings():
+                warnings.filterwarnings("ignore", category=DeprecationWarning)
+                try:
+                    self.assertFormError(
+                        response.context["form"], "import_file", target_msg
+                    )
+                except TypeError:
+                    self.assertFormError(response, "form", "import_file", target_msg)
+        else:
+            self.assertFormError(response, "form", "import_file", target_msg)
+
     @ignore_widget_deprecation_warning
     def test_delete_from_admin(self):
         # test delete from admin site (see #432)