Move SnippetViewSet.get_edit_handler() to ModelViewSet

However, keep the logic for falling back to extracting panel definitions
from the model class as snippets-specific. ModelViewSets are likely used
with models that are more low-level and thus we want developers to
explicitly define the fields that are editable in the admin, just like
how Django's ModelForm works.
pull/10830/head
Sage Abdullah 2023-08-24 15:06:48 +01:00
rodzic 0af4dd5fd9
commit b4881cad64
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: EB1A33CC51CC0217
4 zmienionych plików z 64 dodań i 32 usunięć

Wyświetl plik

@ -77,6 +77,7 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
Used in place of :attr:`form_fields` to indicate that all of the model's fields except the ones listed here should appear in the create / edit forms. Either ``form_fields`` or ``exclude_form_fields`` must be supplied (unless :meth:`get_form_class` is being overridden).
.. automethod:: get_form_class
.. automethod:: get_edit_handler
.. autoattribute:: menu_label
@ -195,7 +196,6 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: chooser_viewset_class
.. automethod:: get_queryset
.. automethod:: get_edit_handler
.. automethod:: get_form_class
.. automethod:: get_index_template
.. automethod:: get_index_results_template
.. automethod:: get_create_template

Wyświetl plik

@ -10,6 +10,7 @@ from wagtail.admin.admin_url_finder import (
ModelAdminURLFinder,
register_admin_url_finder,
)
from wagtail.admin.panels.group import ObjectList
from wagtail.admin.views import generic
from wagtail.admin.views.generic import history, usage
from wagtail.models import ReferenceIndex
@ -151,6 +152,7 @@ class ModelViewSet(ViewSet):
def get_add_view_kwargs(self, **kwargs):
return {
"panel": self._edit_handler,
"form_class": self.get_form_class(),
"template_name": self.create_template_name,
**kwargs,
@ -158,6 +160,7 @@ class ModelViewSet(ViewSet):
def get_edit_view_kwargs(self, **kwargs):
return {
"panel": self._edit_handler,
"form_class": self.get_form_class(for_update=True),
"template_name": self.edit_template_name,
**kwargs,
@ -507,6 +510,11 @@ class ModelViewSet(ViewSet):
"""
Returns the form class to use for the create / edit forms.
"""
# If an edit handler is defined, use it to construct the form class.
if self._edit_handler:
return self._edit_handler.get_form_class()
# Otherwise, use Django's modelform_factory.
fields = self.get_form_fields()
exclude = self.get_exclude_form_fields()
@ -535,6 +543,37 @@ class ModelViewSet(ViewSet):
"""
return getattr(self, "exclude_form_fields", None)
def get_edit_handler(self):
"""
Returns the appropriate edit handler for this ``ModelViewSet`` class.
It can be defined either on the model itself or on the ``ModelViewSet``,
as the ``edit_handler`` or ``panels`` properties. If none of these are
defined, it will return ``None`` and the form will be constructed as
a Django form using :meth:`get_form_class` (without using
:ref:`forms_panels_overview`).
"""
if hasattr(self, "edit_handler"):
edit_handler = self.edit_handler
elif hasattr(self, "panels"):
panels = self.panels
edit_handler = ObjectList(panels)
elif hasattr(self.model, "edit_handler"):
edit_handler = self.model.edit_handler
elif hasattr(self.model, "panels"):
panels = self.model.panels
edit_handler = ObjectList(panels)
else:
return None
return edit_handler.bind_to_model(self.model)
@cached_property
def _edit_handler(self):
"""
An edit handler that has been bound to the model class,
to be used across views.
"""
return self.get_edit_handler()
@property
def url_finder_class(self):
return type(

Wyświetl plik

@ -13,8 +13,7 @@ from django.utils.translation import gettext_lazy
from wagtail import hooks
from wagtail.admin.checks import check_panels_in_model
from wagtail.admin.panels.group import ObjectList
from wagtail.admin.panels.model_utils import extract_panel_definitions_from_model_class
from wagtail.admin.panels import ObjectList, extract_panel_definitions_from_model_class
from wagtail.admin.ui.components import MediaContainer
from wagtail.admin.ui.side_panels import PreviewSidePanel
from wagtail.admin.ui.tables import (
@ -548,6 +547,12 @@ class WorkflowHistoryDetailView(
class SnippetViewSet(ModelViewSet):
"""
A viewset that instantiates the admin views for snippets.
All attributes and methods from
:class:`~wagtail.admin.viewsets.model.ModelViewSet` are available.
For more information on how to use this class,
see :ref:`wagtailsnippets_custom_admin_views`.
"""
#: The model class to be registered as a snippet with this viewset.
@ -667,9 +672,6 @@ class SnippetViewSet(ModelViewSet):
self, "menu_item_is_registered", bool(self.menu_hook)
)
# This edit handler has been bound to the model and is used for the views.
self._edit_handler = self.get_edit_handler()
@cached_property
def url_prefix(self):
# SnippetViewSet historically allows overriding the URL prefix via the
@ -731,14 +733,12 @@ class SnippetViewSet(ModelViewSet):
def get_add_view_kwargs(self, **kwargs):
return super().get_add_view_kwargs(
panel=self._edit_handler,
preview_url_name=self.get_url_name("preview_on_add"),
**kwargs,
)
def get_edit_view_kwargs(self, **kwargs):
return super().get_edit_view_kwargs(
panel=self._edit_handler,
preview_url_name=self.get_url_name("preview_on_edit"),
workflow_history_url_name=self.get_url_name("workflow_history"),
confirm_workflow_cancellation_url_name=self.get_url_name(
@ -1257,31 +1257,19 @@ class SnippetViewSet(ModelViewSet):
def get_edit_handler(self):
"""
Returns the appropriate edit handler for this ``SnippetViewSet`` class.
It can be defined either on the model itself or on the ``SnippetViewSet``,
as the ``edit_handler`` or ``panels`` properties. Falls back to
extracting panel / edit handler definitions from the model class.
Like :meth:`ModelViewSet.get_edit_handler()
<wagtail.admin.viewsets.model.ModelViewSet.get_edit_handler>`,
but falls back to extracting panel definitions from the model class
if no edit handler is defined.
"""
if hasattr(self, "edit_handler"):
edit_handler = self.edit_handler
elif hasattr(self, "panels"):
panels = self.panels
edit_handler = ObjectList(panels)
elif hasattr(self.model, "edit_handler"):
edit_handler = self.model.edit_handler
elif hasattr(self.model, "panels"):
panels = self.model.panels
edit_handler = ObjectList(panels)
else:
exclude = self.get_exclude_form_fields()
panels = extract_panel_definitions_from_model_class(
self.model, exclude=exclude
)
edit_handler = ObjectList(panels)
return edit_handler.bind_to_model(self.model)
edit_handler = super().get_edit_handler()
if edit_handler:
return edit_handler
def get_form_class(self, for_update=False):
return self._edit_handler.get_form_class()
exclude = self.get_exclude_form_fields()
panels = extract_panel_definitions_from_model_class(self.model, exclude=exclude)
edit_handler = ObjectList(panels)
return edit_handler.bind_to_model(self.model)
def register_chooser_viewset(self):
viewsets.register(self.chooser_viewset)

Wyświetl plik

@ -11,6 +11,7 @@ from django.utils.translation import gettext_lazy
from wagtail.admin import messages
from wagtail.admin.auth import user_passes_test
from wagtail.admin.filters import WagtailFilterSet
from wagtail.admin.panels import FieldPanel
from wagtail.admin.ui.tables import BooleanColumn, UpdatedAtColumn
from wagtail.admin.views.generic import DeleteView, EditView, IndexView
from wagtail.admin.viewsets.base import ViewSet, ViewSetGroup
@ -206,7 +207,6 @@ class FeatureCompleteToyViewSet(ModelViewSet):
url_prefix = "feature-complete-toy"
menu_label = "Feature Complete Toys"
icon = "media"
exclude_form_fields = ()
template_prefix = "customprefix/"
index_template_name = "tests/fctoy_index.html"
list_display = ["name", BooleanColumn("is_cool"), UpdatedAtColumn()]
@ -220,6 +220,11 @@ class FeatureCompleteToyViewSet(ModelViewSet):
inspect_view_enabled = True
inspect_view_fields = ["strid", "release_date"]
panels = [
FieldPanel("name"),
FieldPanel("release_date"),
]
class FCToyAlt1ViewSet(ModelViewSet):
model = FeatureCompleteToy