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

Issue:
Confirmation page displays incorrect fields
**Describe the bug**

This has been introduced in v4.

When previewing an import via the Admin site, the field order is incorrect.  (note 'display classes' field)

### v4 (incorrect)

![image](https://github.com/django-import-export/django-import-export/assets/6249838/b47a51d5-0a7a-4326-94c8-a90ffdb30356)


### v3 (correct)

![Screenshot 2024-04-04 at 11 45 11](https://github.com/django-import-export/django-import-export/assets/6249838/f36429bb-ff0d-4c6f-be71-a706d2748ca3)


Note that if you confirm the import, then the file is imported correctly in both cases.

I think this was introduced [here](https://github.com/django-import-export/django-import-export/pull/1626/files).

I believe it is caused by declaring a `fields` entry.  The rows will use this ordering but the header will not.  You can reproduce with this declaration in the example app:

```
class BookResource(ModelResource):
    class Meta:
        model = Book

        fields = (
            "id",
            "author_email",
            "name",
            "author",
            "imported",
            "published",
            "published_time",
            "price",
            "added",
            "categories",
        )
```



Discussion:

Resolving patch:
diff --git a/import_export/resources.py b/import_export/resources.py
--- a/import_export/resources.py
+++ b/import_export/resources.py
@@ -579,7 +579,7 @@ def get_diff_headers(self):
         """
         Diff representation headers.
         """
-        return self.get_user_visible_headers()
+        return [force_str(field.column_name) for field in self.get_import_fields()]
 
     def before_import(self, dataset, **kwargs):
         r"""
@@ -1051,12 +1051,6 @@ def get_export_headers(self, fields=None):
 
         return headers
 
-    def get_user_visible_headers(self):
-        headers = [
-            force_str(field.column_name) for field in self.get_user_visible_fields()
-        ]
-        return headers
-
     def get_user_visible_fields(self):
         return self.get_fields()
 


Test patch:
diff --git a/tests/core/admin.py b/tests/core/admin.py
--- a/tests/core/admin.py
+++ b/tests/core/admin.py
@@ -55,6 +55,11 @@ def filter_export(self, queryset, *args, **kwargs):
 
     class Meta:
         model = EBook
+        fields = (
+            "id",
+            "author_email",
+            "name",
+        )
 
 
 class CustomBookAdmin(ImportExportModelAdmin):
diff --git a/tests/core/tests/admin_integration/mixins.py b/tests/core/tests/admin_integration/mixins.py
--- a/tests/core/tests/admin_integration/mixins.py
+++ b/tests/core/tests/admin_integration/mixins.py
@@ -9,6 +9,7 @@
 class AdminTestMixin(object):
     category_change_url = "/admin/core/category/"
     book_import_url = "/admin/core/book/import/"
+    ebook_import_url = "/admin/core/ebook/import/"
     book_process_import_url = "/admin/core/book/process_import/"
     legacybook_import_url = "/admin/core/legacybook/import/"
     legacybook_process_import_url = "/admin/core/legacybook/process_import/"
@@ -24,7 +25,14 @@ def setUp(self):
         self.client.login(username="admin", password="password")
 
     def _do_import_post(
-        self, url, filename, input_format=0, encoding=None, resource=None, follow=False
+        self,
+        url,
+        filename,
+        input_format=0,
+        encoding=None,
+        resource=None,
+        follow=False,
+        data=None,
     ):
         input_format = input_format
         filename = os.path.join(
@@ -35,10 +43,14 @@ def _do_import_post(
             filename,
         )
         with open(filename, "rb") as f:
-            data = {
-                "format": str(input_format),
-                "import_file": f,
-            }
+            if data is None:
+                data = dict()
+            data.update(
+                {
+                    "format": str(input_format),
+                    "import_file": f,
+                }
+            )
             if encoding:
                 BookAdmin.from_encoding = encoding
             if resource:
diff --git a/tests/core/tests/admin_integration/test_export.py b/tests/core/tests/admin_integration/test_export.py
--- a/tests/core/tests/admin_integration/test_export.py
+++ b/tests/core/tests/admin_integration/test_export.py
@@ -327,10 +327,8 @@ def test_export_filters_by_form_param(self):
             'attachment; filename="EBook-{}.csv"'.format(date_str),
         )
         self.assertEqual(
-            b"id,name,author,author_email,imported,published,"
-            b"published_time,price,added,categories\r\n"
-            b"5,The Man with the Golden Gun,5,ian@example.com,"
-            b"0,1965-04-01,21:00:00,5.00,,2\r\n",
+            b"id,author_email,name\r\n"
+            b"5,ian@example.com,The Man with the Golden Gun\r\n",
             response.content,
         )
 
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
@@ -984,3 +984,36 @@ def test_import_action_binary(self):
             str_in_response="Import finished: 1 new, 0 updated, "
             + "0 deleted and 0 skipped books.",
         )
+
+
+class ConfirmImportPreviewOrderTest(AdminTestMixin, TestCase):
+    """Test preview order displayed correctly (issue 1784)."""
+
+    fixtures = ["author"]
+
+    @ignore_widget_deprecation_warning
+    def test_import_preview_order(self):
+        author_id = Author.objects.first().id
+        response = self._do_import_post(
+            self.ebook_import_url,
+            "books.csv",
+            input_format="0",
+            data={"author": author_id},
+        )
+        # test header rendered in correct order
+        target_header_re = (
+            r"<thead>[\\n\s]+<tr>[\\n\s]+<th></th>[\\n\s]+<th>id</th>"
+            r"[\\n\s]+<th>author_email</th>[\\n\s]+<th>name</th>[\\n\s]+</tr>[\\n\s]+"
+            "</thead>"
+        )
+        self.assertRegex(str(response.content), target_header_re)
+        # test row rendered in correct order
+        target_row_re = (
+            r'<tr class="new">[\\n\s]+'
+            r'<td class="import-type">[\\n\s]+New[\\n\s]+</td>[\\n\s]+'
+            r'<td><ins style="background:#e6ffe6;">1</ins></td>[\\n\s]+'
+            r'<td><ins style="background:#e6ffe6;">test@example.com</ins></td>[\\n\s]+'
+            r'<td><ins style="background:#e6ffe6;">Some book</ins></td>[\\n\s]+'
+            "</tr>"
+        )
+        self.assertRegex(str(response.content), target_row_re)
diff --git a/tests/core/tests/test_resources/test_diffs.py b/tests/core/tests/test_resources/test_diffs.py
--- a/tests/core/tests/test_resources/test_diffs.py
+++ b/tests/core/tests/test_resources/test_diffs.py
@@ -99,7 +99,7 @@ class Meta:
             "import_export.resources.Resource.get_import_fields"
         ) as mock_get_import_fields:
             resource.import_data(self.dataset, dry_run=True)
-            self.assertEqual(2, mock_get_import_fields.call_count)
+            self.assertEqual(3, mock_get_import_fields.call_count)
 
 
 class SkipHtmlDiffTest(TestCase):