Repository: wagtail/wagtail

Issue:
Allow customisation of `SnippetChooserViewSet`
https://github.com/wagtail/wagtail/blob/4246c0b703bccc9aafb6f86524bbbdb55c3c9e1e/wagtail/snippets/models.py#L92-L102

I have one special snipped model and would like to show all >300 elements on a single page bypassing paginator (inline-block).


Discussion:

Resolving patch:
diff --git a/wagtail/snippets/models.py b/wagtail/snippets/models.py
--- a/wagtail/snippets/models.py
+++ b/wagtail/snippets/models.py
@@ -4,19 +4,13 @@
 from django.contrib.auth import get_permission_codename
 from django.contrib.auth.models import Permission
 from django.contrib.contenttypes.models import ContentType
-from django.core import checks
 from django.db import DEFAULT_DB_ALIAS
-from django.db.models import ForeignKey
 from django.urls import reverse
 from django.utils.module_loading import import_string
 
-from wagtail.admin.checks import check_panels_in_model
-from wagtail.admin.forms.models import register_form_field_override
 from wagtail.admin.viewsets import viewsets
 from wagtail.models import DraftStateMixin, LockableMixin, ReferenceIndex, WorkflowMixin
 
-from .widgets import AdminSnippetChooser
-
 SNIPPET_MODELS = []
 
 
@@ -91,7 +85,6 @@ def _register_snippet_immediately(model, viewset=None):
         # Do not create duplicate registrations of the same model
         return
 
-    from wagtail.snippets.views.chooser import SnippetChooserViewSet
     from wagtail.snippets.views.snippets import SnippetViewSet
 
     model.get_usage = lambda obj: ReferenceIndex.get_references_to(
@@ -112,28 +105,11 @@ def _register_snippet_immediately(model, viewset=None):
         url_prefix=model.get_admin_base_path(),
     )
 
-    chooser_viewset = SnippetChooserViewSet(
-        f"wagtailsnippetchoosers_{model._meta.app_label}_{model._meta.model_name}",
-        model=model,
-        url_prefix=f"snippets/choose/{model._meta.app_label}/{model._meta.model_name}",
-    )
-
     viewsets.register(admin_viewset)
-    viewsets.register(chooser_viewset)
 
     SNIPPET_MODELS.append(model)
     SNIPPET_MODELS.sort(key=lambda x: x._meta.verbose_name)
 
-    @checks.register("panels")
-    def modeladmin_model_check(app_configs, **kwargs):
-        errors = check_panels_in_model(model, "snippets")
-        return errors
-
-    # Set up admin model forms to use AdminSnippetChooser for any ForeignKey to this model
-    register_form_field_override(
-        ForeignKey, to=model, override={"widget": AdminSnippetChooser(model=model)}
-    )
-
 
 def get_snippet_usage_url(self):
     return reverse(
diff --git a/wagtail/snippets/views/chooser.py b/wagtail/snippets/views/chooser.py
--- a/wagtail/snippets/views/chooser.py
+++ b/wagtail/snippets/views/chooser.py
@@ -1,3 +1,4 @@
+from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
 
 from wagtail.admin.ui.tables import LiveStatusTagColumn
@@ -11,6 +12,7 @@
 )
 from wagtail.admin.viewsets.chooser import ChooserViewSet
 from wagtail.models import DraftStateMixin
+from wagtail.snippets.widgets import AdminSnippetChooser
 
 
 class BaseSnippetChooseView(BaseChooseView):
@@ -64,8 +66,11 @@ class SnippetChosenMultipleView(ChosenMultipleView):
 
 
 class SnippetChooserViewSet(ChooserViewSet):
-    register_widget = False  # registering the snippet chooser widget for a given model is done in register_snippet
     choose_view_class = ChooseView
     choose_results_view_class = ChooseResultsView
     chosen_view_class = SnippetChosenView
     chosen_multiple_view_class = SnippetChosenMultipleView
+
+    @cached_property
+    def widget_class(self):
+        return AdminSnippetChooser(model=self.model)
diff --git a/wagtail/snippets/views/snippets.py b/wagtail/snippets/views/snippets.py
--- a/wagtail/snippets/views/snippets.py
+++ b/wagtail/snippets/views/snippets.py
@@ -4,6 +4,7 @@
 import django_filters
 from django.apps import apps
 from django.contrib.admin.utils import quote, unquote
+from django.core import checks
 from django.core.exceptions import PermissionDenied
 from django.db import transaction
 from django.http import Http404
@@ -14,6 +15,7 @@
 from django.utils.translation import gettext_lazy, ngettext
 
 from wagtail.admin.admin_url_finder import register_admin_url_finder
+from wagtail.admin.checks import check_panels_in_model
 from wagtail.admin.filters import DateRangePickerWidget, WagtailFilterSet
 from wagtail.admin.panels import get_edit_handler
 from wagtail.admin.ui.tables import (
@@ -32,6 +34,7 @@
 from wagtail.admin.views.generic.preview import PreviewOnEdit as PreviewOnEditView
 from wagtail.admin.views.generic.preview import PreviewRevision
 from wagtail.admin.views.reports.base import ReportView
+from wagtail.admin.viewsets import viewsets
 from wagtail.admin.viewsets.base import ViewSet
 from wagtail.log_actions import log
 from wagtail.log_actions import registry as log_registry
@@ -49,6 +52,7 @@
 from wagtail.snippets.models import SnippetAdminURLFinder, get_snippet_models
 from wagtail.snippets.permissions import user_can_edit_snippet_type
 from wagtail.snippets.side_panels import SnippetSidePanels
+from wagtail.snippets.views.chooser import SnippetChooserViewSet
 
 
 # == Helper functions ==
@@ -754,6 +758,8 @@ class SnippetViewSet(ViewSet):
     #: The view class to use for the workflow history detail view; must be a subclass of ``wagtail.snippet.views.snippets.WorkflowHistoryDetailView``.
     workflow_history_detail_view_class = WorkflowHistoryDetailView
 
+    chooser_viewset_class = SnippetChooserViewSet
+
     def __init__(self, name, **kwargs):
         super().__init__(name, **kwargs)
         self.preview_enabled = issubclass(self.model, PreviewableMixin)
@@ -762,6 +768,9 @@ def __init__(self, name, **kwargs):
         self.workflow_enabled = issubclass(self.model, WorkflowMixin)
         self.locking_enabled = issubclass(self.model, LockableMixin)
 
+        self.app_label = self.model._meta.app_label
+        self.model_name = self.model._meta.model_name
+
         if not self.list_display:
             self.list_display = self.index_view_class.list_display.copy()
             if self.draftstate_enabled:
@@ -1017,24 +1026,38 @@ def workflow_history_detail_view(self):
     def redirect_to_edit_view(self):
         return partial(
             redirect_to_edit,
-            app_label=self.model._meta.app_label,
-            model_name=self.model._meta.model_name,
+            app_label=self.app_label,
+            model_name=self.model_name,
         )
 
     @property
     def redirect_to_delete_view(self):
         return partial(
             redirect_to_delete,
-            app_label=self.model._meta.app_label,
-            model_name=self.model._meta.model_name,
+            app_label=self.app_label,
+            model_name=self.model_name,
         )
 
     @property
     def redirect_to_usage_view(self):
         return partial(
             redirect_to_usage,
-            app_label=self.model._meta.app_label,
-            model_name=self.model._meta.model_name,
+            app_label=self.app_label,
+            model_name=self.model_name,
+        )
+
+    @property
+    def chooser_viewset(self):
+        return self.chooser_viewset_class(
+            f"wagtailsnippetchoosers_{self.app_label}_{self.model_name}",
+            model=self.model,
+            url_prefix=f"snippets/choose/{self.app_label}/{self.model_name}",
+        )
+
+    @property
+    def url_finder_class(self):
+        return type(
+            "_SnippetAdminURLFinder", (SnippetAdminURLFinder,), {"model": self.model}
         )
 
     def get_urlpatterns(self):
@@ -1151,9 +1174,17 @@ def get_urlpatterns(self):
 
         return urlpatterns + legacy_redirects
 
+    def register_admin_url_finder(self):
+        register_admin_url_finder(self.model, self.url_finder_class)
+
+    def register_model_check(self):
+        def snippets_model_check(app_configs, **kwargs):
+            return check_panels_in_model(self.model, "snippets")
+
+        checks.register(snippets_model_check, "panels")
+
     def on_register(self):
         super().on_register()
-        url_finder_class = type(
-            "_SnippetAdminURLFinder", (SnippetAdminURLFinder,), {"model": self.model}
-        )
-        register_admin_url_finder(self.model, url_finder_class)
+        viewsets.register(self.chooser_viewset)
+        self.register_admin_url_finder()
+        self.register_model_check()


Test patch: