From 7cad7c4f0e740057e10cf3f1922487b4ae2c8bf6 Mon Sep 17 00:00:00 2001
From: Matt Westcott <matt@west.co.tt>
Date: Sat, 7 Sep 2024 03:40:40 +0100
Subject: [PATCH] Reinstate support for generic IndexView without model
 attribute

000d417ec92ba8218653b4a1456e35666fc49254 (in #12236) skips the check that `self.model` is non-null in `is_searchable`. This means that it is no longer possible to define IndexView subclasses without a model property, which was previously valid - for example this one from wagtail-review:

https://github.com/wagtail-nest/wagtail-review/blob/ce2f6d814b99fbdc1736f0e427ee96bf2a7f2c09/wagtail_review/views/admin.py#L98-L104
---
 wagtail/admin/tests/test_views_generic.py | 13 +++++++++++++
 wagtail/admin/views/generic/models.py     |  2 +-
 wagtail/test/testapp/urls.py              |  5 +++++
 wagtail/test/testapp/views.py             |  5 +++++
 4 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/wagtail/admin/tests/test_views_generic.py b/wagtail/admin/tests/test_views_generic.py
index 0b5bc67e8b..5f3a425ac8 100644
--- a/wagtail/admin/tests/test_views_generic.py
+++ b/wagtail/admin/tests/test_views_generic.py
@@ -24,6 +24,19 @@ class TestGenericIndexView(WagtailTestUtils, TestCase):
         self.assertEqual(h1.text.strip(), "Model with string type primary keys")
 
 
+class TestGenericIndexViewWithoutModel(WagtailTestUtils, TestCase):
+    fixtures = ["test.json"]
+
+    def get(self, params={}):
+        return self.client.get(reverse("testapp_generic_index_without_model"), params)
+
+    def test_non_integer_primary_key(self):
+        response = self.get()
+        self.assertEqual(response.status_code, 200)
+        response_object_count = response.context_data["object_list"].count()
+        self.assertEqual(response_object_count, 3)
+
+
 class TestGenericEditView(WagtailTestUtils, TestCase):
     fixtures = ["test.json"]
 
diff --git a/wagtail/admin/views/generic/models.py b/wagtail/admin/views/generic/models.py
index fafc8c45f0..8a6970d46a 100644
--- a/wagtail/admin/views/generic/models.py
+++ b/wagtail/admin/views/generic/models.py
@@ -98,7 +98,7 @@ class IndexView(
     def is_searchable(self):
         # Do not automatically enable search if the model is not indexed and
         # search_fields is not defined.
-        if not class_is_indexed(self.model) and not self.search_fields:
+        if not (self.model and class_is_indexed(self.model)) and not self.search_fields:
             return False
 
         # Require the results-only view to be set up before enabling search
diff --git a/wagtail/test/testapp/urls.py b/wagtail/test/testapp/urls.py
index 3abb152f0a..0cb86f0a1f 100644
--- a/wagtail/test/testapp/urls.py
+++ b/wagtail/test/testapp/urls.py
@@ -14,4 +14,9 @@ urlpatterns = [
         views.TestDeleteView.as_view(),
         name="testapp_generic_delete",
     ),
+    path(
+        "test-index-without-model/",
+        views.TestIndexViewWithoutModel.as_view(),
+        name="testapp_generic_index_without_model",
+    ),
 ]
diff --git a/wagtail/test/testapp/views.py b/wagtail/test/testapp/views.py
index 49ba056e34..22be074cb0 100644
--- a/wagtail/test/testapp/views.py
+++ b/wagtail/test/testapp/views.py
@@ -68,6 +68,11 @@ class TestIndexView(IndexView):
     context_object_name = "test_object"
 
 
+class TestIndexViewWithoutModel(IndexView):
+    def get_base_queryset(self):
+        return ModelWithStringTypePrimaryKey.objects.all()
+
+
 class CustomModelEditForm(forms.ModelForm):
     class Meta:
         model = ModelWithStringTypePrimaryKey