Allow admin URL customisation for snippet chooser views via SnippetViewSet

pull/10263/head
Sage Abdullah 2023-03-16 16:44:32 +00:00 zatwierdzone przez Matt Westcott
rodzic 9f070f6262
commit b713a1753e
6 zmienionych plików z 78 dodań i 6 usunięć

Wyświetl plik

@ -83,6 +83,8 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: list_display
.. autoattribute:: admin_url_namespace
.. autoattribute:: base_url_path
.. autoattribute:: chooser_admin_url_namespace
.. autoattribute:: chooser_base_url_path
.. autoattribute:: filterset_class
.. autoattribute:: index_view_class
.. autoattribute:: add_view_class
@ -101,4 +103,6 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: unlock_view_class
.. automethod:: get_admin_url_namespace
.. automethod:: get_admin_base_path
.. automethod:: get_chooser_admin_url_namespace
.. automethod:: get_chooser_admin_base_path
```

Wyświetl plik

@ -571,6 +571,8 @@ You can define a {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.icon` at
The {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.admin_url_namespace` attribute can be set to use a custom URL namespace for the URL patterns of the views. If unset, it defaults to `wagtailsnippets_{app_label}_{model_name}`. Meanwhile, setting {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.base_url_path` allows you to customise the base URL path relative to the Wagtail admin URL. If unset, it defaults to `snippets/app_label/model_name`. If you need further customisations, you can also override the {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_admin_url_namespace` and {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_admin_base_path` methods to override the namespace and base URL path, respectively.
Similar URL customisations are also possible for the snippet chooser views through {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.chooser_admin_url_namespace`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.chooser_base_url_path`, {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_chooser_admin_url_namespace`, and {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_chooser_admin_base_path`.
The {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.list_display` attribute can be set to specify the columns shown on the listing view. You can also add the ability to filter the listing view by defining a {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.filterset_class` attribute on a subclass of `SnippetViewSet`.
For example:

Wyświetl plik

@ -139,9 +139,8 @@ class TestSnippetChooserPanelWithIcon(WagtailTestUtils, TestCase):
self.assertNotIn("icon-snippet", field_html)
def test_chooser_popup(self):
response = self.client.get(
reverse("wagtailsnippetchoosers_tests_fullfeaturedsnippet:choose")
)
chooser_viewset = FullFeaturedSnippet.snippet_viewset.chooser_viewset
response = self.client.get(reverse(chooser_viewset.get_url_name("choose")))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context["header_icon"], "cog")
self.assertContains(response, "icon icon-cog", count=1)
@ -175,12 +174,23 @@ class TestAdminURLs(WagtailTestUtils, TestCase):
viewset.get_url_name("edit"),
"wagtailsnippets_tests_advert:edit",
)
# Chooser namespace
self.assertEqual(
viewset.get_chooser_admin_url_namespace(),
"wagtailsnippetchoosers_tests_advert",
)
# Get specific chooser URL name
self.assertEqual(
viewset.chooser_viewset.get_url_name("choose"),
"wagtailsnippetchoosers_tests_advert:choose",
)
def test_default_admin_base_path(self):
snippet = Advert.objects.create(text="foo")
viewset = snippet.snippet_viewset
pk = quote(snippet.pk)
expected_url = f"/admin/snippets/tests/advert/edit/{pk}/"
expected_choose_url = "/admin/snippets/choose/tests/advert/"
# Accessed via the viewset
self.assertEqual(viewset.get_admin_base_path(), "snippets/tests/advert")
@ -191,6 +201,16 @@ class TestAdminURLs(WagtailTestUtils, TestCase):
# Ensure AdminURLFinder returns the correct URL
url_finder = AdminURLFinder(self.user)
self.assertEqual(url_finder.get_edit_url(snippet), expected_url)
# Chooser base path
self.assertEqual(
viewset.get_chooser_admin_base_path(),
"snippets/choose/tests/advert",
)
# Get specific chooser URL
self.assertEqual(
reverse(viewset.chooser_viewset.get_url_name("choose")),
expected_choose_url,
)
def test_custom_url_namespace(self):
snippet = FullFeaturedSnippet.objects.create(text="customised")
@ -201,12 +221,23 @@ class TestAdminURLs(WagtailTestUtils, TestCase):
self.assertEqual(snippet.get_admin_url_namespace(), "some_namespace")
# Get specific URL name
self.assertEqual(viewset.get_url_name("edit"), "some_namespace:edit")
# Chooser namespace
self.assertEqual(
viewset.get_chooser_admin_url_namespace(),
"my_chooser_namespace",
)
# Get specific chooser URL name
self.assertEqual(
viewset.chooser_viewset.get_url_name("choose"),
"my_chooser_namespace:choose",
)
def test_custom_admin_base_path(self):
snippet = FullFeaturedSnippet.objects.create(text="customised")
viewset = snippet.snippet_viewset
pk = quote(snippet.pk)
expected_url = f"/admin/deep/within/the/admin/edit/{pk}/"
expected_choose_url = "/admin/choose/wisely/"
# Accessed via the viewset
self.assertEqual(viewset.get_admin_base_path(), "deep/within/the/admin")
# Accessed via the model
@ -216,3 +247,13 @@ class TestAdminURLs(WagtailTestUtils, TestCase):
# Ensure AdminURLFinder returns the correct URL
url_finder = AdminURLFinder(self.user)
self.assertEqual(url_finder.get_edit_url(snippet), expected_url)
# Chooser base path
self.assertEqual(
viewset.get_chooser_admin_base_path(),
"choose/wisely",
)
# Get specific chooser URL
self.assertEqual(
reverse(viewset.chooser_viewset.get_url_name("choose")),
expected_choose_url,
)

Wyświetl plik

@ -617,6 +617,14 @@ class SnippetViewSet(ViewSet):
#: If left unset, ``snippets/{app_label}/{model_name}`` is used instead.
base_url_path = None
#: The URL namespace to use for the chooser admin views.
#: If left unset, ``wagtailsnippetchoosers_{app_label}_{model_name}`` is used instead.
chooser_admin_url_namespace = None
#: The base URL path to use for the chooser admin views.
#: If left unset, ``snippets/choose/{app_label}/{model_name}`` is used instead.
chooser_base_url_path = None
#: The view class to use for the index view; must be a subclass of ``wagtail.snippet.views.snippets.IndexView``.
index_view_class = IndexView
@ -988,9 +996,9 @@ class SnippetViewSet(ViewSet):
@property
def chooser_viewset(self):
return self.chooser_viewset_class(
f"wagtailsnippetchoosers_{self.app_label}_{self.model_name}",
self.get_chooser_admin_url_namespace(),
model=self.model,
url_prefix=f"snippets/choose/{self.app_label}/{self.model_name}",
url_prefix=self.get_chooser_admin_base_path(),
icon=self.icon,
)
@ -1009,6 +1017,21 @@ class SnippetViewSet(ViewSet):
return self.base_url_path.strip().strip("/")
return f"snippets/{self.app_label}/{self.model_name}"
def get_chooser_admin_url_namespace(self):
"""Returns the URL namespace for the chooser admin URLs for this model."""
if self.chooser_admin_url_namespace:
return self.chooser_admin_url_namespace
return f"wagtailsnippetchoosers_{self.app_label}_{self.model_name}"
def get_chooser_admin_base_path(self):
"""
Returns the base path for the chooser admin URLs for this model.
The returned string must not begin or end with a slash.
"""
if self.chooser_base_url_path:
return self.chooser_base_url_path.strip().strip("/")
return f"snippets/choose/{self.app_label}/{self.model_name}"
@property
def url_finder_class(self):
return type(

Wyświetl plik

@ -28,7 +28,7 @@ class AdminSnippetChooser(BaseChooser):
def get_chooser_modal_url(self):
try:
return reverse(
f"wagtailsnippetchoosers_{self.model._meta.app_label}_{self.model._meta.model_name}:choose"
self.model.snippet_viewset.chooser_viewset.get_url_name("choose")
)
except NoReverseMatch:
# This most likely failed because the model is not registered as a snippet.

Wyświetl plik

@ -234,6 +234,8 @@ class FullFeaturedSnippetViewSet(SnippetViewSet):
icon = "cog"
admin_url_namespace = "some_namespace"
base_url_path = "deep/within/the/admin"
chooser_admin_url_namespace = "my_chooser_namespace"
chooser_base_url_path = "choose/wisely"
register_snippet(FullFeaturedSnippet, viewset=FullFeaturedSnippetViewSet)