From c23c6b3a22ae7c3debdfa5c782a07497a290e3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Braghi=C8=99?= Date: Tue, 25 Feb 2025 17:56:06 +0000 Subject: [PATCH 1/2] Tidy up the Bundle viewset and chooser search --- cms/bundles/models.py | 1 + cms/bundles/tests/test_viewsets.py | 33 ++++++++++++++++++++++++++++++ cms/bundles/viewsets.py | 27 ++++++++++++++---------- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/cms/bundles/models.py b/cms/bundles/models.py index 95bee527..25b79bb8 100644 --- a/cms/bundles/models.py +++ b/cms/bundles/models.py @@ -122,6 +122,7 @@ class Bundle(index.Indexed, ClusterableModel, models.Model): # type: ignore[dja search_fields: ClassVar[list[index.BaseField]] = [ index.SearchField("name"), index.AutocompleteField("name"), + index.FilterField("status"), ] def __str__(self) -> str: diff --git a/cms/bundles/tests/test_viewsets.py b/cms/bundles/tests/test_viewsets.py index dac95645..5490bca9 100644 --- a/cms/bundles/tests/test_viewsets.py +++ b/cms/bundles/tests/test_viewsets.py @@ -12,6 +12,7 @@ from cms.bundles.models import Bundle from cms.bundles.tests.factories import BundleFactory from cms.bundles.tests.utils import grant_all_bundle_permissions, make_bundle_viewer +from cms.bundles.viewsets import bundle_chooser_viewset from cms.release_calendar.viewsets import FutureReleaseCalendarChooserWidget from cms.users.tests.factories import GroupFactory, UserFactory @@ -236,6 +237,14 @@ def test_index_view(self): self.assertContains(response, "Released", 2) # status + status filter self.assertContains(response, "Approved", 5) # status + status filter, approved at/by + self.assertContains(response, self.released_bundle.name) + self.assertContains(response, self.approved_bundle.name) + + def test_index_view_search(self): + response = self.client.get(f"{self.bundle_index_url}?q=release") + self.assertContains(response, self.released_bundle.name) + self.assertNotContains(response, self.approved_bundle.name) + def test_bundle_form_uses_release_calendar_chooser_widget(self): form_class = get_edit_handler(Bundle).get_form_class() form = form_class(instance=self.bundle) @@ -254,3 +263,27 @@ def test_bundle_form_uses_release_calendar_chooser_widget(self): self.bundle_add_url, ) self.assertContains(response, "Choose Release Calendar page") + + def test_chooser_viewset(self): + pending_bundle = BundleFactory(name="Pending") + response = self.client.get(bundle_chooser_viewset.widget_class().get_chooser_modal_url()) + + self.assertContains(response, pending_bundle.name) + self.assertNotContains(response, self.released_bundle.name) + self.assertNotContains(response, self.approved_bundle.name) + + def test_chooser_search(self): + pending_bundle = BundleFactory(name="Pending") + chooser_results_url = reverse(bundle_chooser_viewset.get_url_name("choose_results")) + + response = self.client.get(f"{chooser_results_url}?q=approve") + + self.assertNotContains(response, pending_bundle.name) + self.assertNotContains(response, self.released_bundle.name) + self.assertNotContains(response, self.approved_bundle.name) + + response = self.client.get(f"{chooser_results_url}?q=pending") + + self.assertContains(response, pending_bundle.name) + self.assertNotContains(response, self.released_bundle.name) + self.assertNotContains(response, self.approved_bundle.name) diff --git a/cms/bundles/viewsets.py b/cms/bundles/viewsets.py index 8da0ce60..68a2d75b 100644 --- a/cms/bundles/viewsets.py +++ b/cms/bundles/viewsets.py @@ -11,7 +11,7 @@ from django.utils.translation import gettext as _ from wagtail.admin.ui.tables import Column, DateColumn, UpdatedAtColumn, UserColumn from wagtail.admin.views.generic import CreateView, EditView, IndexView, InspectView -from wagtail.admin.views.generic.chooser import ChooseView +from wagtail.admin.views.generic.chooser import ChooseResultsView, ChooseView from wagtail.admin.viewsets.chooser import ChooserViewSet from wagtail.admin.viewsets.model import ModelViewSet from wagtail.log_actions import log @@ -222,9 +222,9 @@ class BundleIndexView(IndexView): model = Bundle - def get_queryset(self) -> QuerySet[Bundle]: + def get_base_queryset(self) -> QuerySet[Bundle]: """Modifies the Bundle queryset with the related created_by ForeignKey selected to avoid N+1 queries.""" - queryset: QuerySet[Bundle] = super().get_queryset() + queryset: QuerySet[Bundle] = super().get_base_queryset() return queryset.select_related("created_by") @@ -254,24 +254,28 @@ def columns(self) -> list[Column]: ] -class BundleChooseView(ChooseView): - """The Bundle choose view class. Used in choosers.""" - +class BundleChooseViewMixin: icon = "boxes-stacked" @property def columns(self) -> list[Column]: """Defines the list of desired columns in the chooser.""" return [ - *super().columns, + *super().columns, # type: ignore[misc] Column("scheduled_publication_date"), UserColumn("created_by"), ] - def get_object_list(self) -> QuerySet[Bundle]: - """Overrides the default object list to only fetch the fields we're using.""" - queryset: QuerySet[Bundle] = Bundle.objects.select_related("created_by").only("name", "created_by") - return queryset + # def get_object_list(self) -> QuerySet[Bundle]: + # """Overrides the default object list to only fetch the fields we're using.""" + # queryset: QuerySet[Bundle] = Bundle.objects.editable().select_related("created_by").only("name", "created_by") + # return queryset + + +class BundleChooseView(BundleChooseViewMixin, ChooseView): ... + + +class BundleChooseResultsView(BundleChooseViewMixin, ChooseResultsView): ... class BundleChooserViewSet(ChooserViewSet): @@ -280,6 +284,7 @@ class BundleChooserViewSet(ChooserViewSet): model = Bundle icon = "boxes-stacked" choose_view_class = BundleChooseView + choose_results_view_class = BundleChooseResultsView def get_object_list(self) -> QuerySet[Bundle]: """Only return editable bundles.""" From 8e427fc80748880a582df228249ebf800290de9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Braghi=C8=99?= Date: Wed, 26 Feb 2025 10:13:43 +0000 Subject: [PATCH 2/2] Tidy up --- cms/bundles/viewsets.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/cms/bundles/viewsets.py b/cms/bundles/viewsets.py index 68a2d75b..11809ad3 100644 --- a/cms/bundles/viewsets.py +++ b/cms/bundles/viewsets.py @@ -266,10 +266,10 @@ def columns(self) -> list[Column]: UserColumn("created_by"), ] - # def get_object_list(self) -> QuerySet[Bundle]: - # """Overrides the default object list to only fetch the fields we're using.""" - # queryset: QuerySet[Bundle] = Bundle.objects.editable().select_related("created_by").only("name", "created_by") - # return queryset + def get_object_list(self) -> QuerySet[Bundle]: + """Overrides the default object list to only fetch the fields we're using.""" + queryset: QuerySet[Bundle] = Bundle.objects.editable().select_related("created_by").only("name", "created_by") + return queryset class BundleChooseView(BundleChooseViewMixin, ChooseView): ... @@ -286,11 +286,6 @@ class BundleChooserViewSet(ChooserViewSet): choose_view_class = BundleChooseView choose_results_view_class = BundleChooseResultsView - def get_object_list(self) -> QuerySet[Bundle]: - """Only return editable bundles.""" - queryset: QuerySet[Bundle] = self.model.objects.editable() - return queryset - class BundleViewSet(ModelViewSet): """The viewset class for Bundle.