diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a09518533e..f67a4ce1d3 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -15,6 +15,7 @@ Changelog * Add informational Codecov status checks for GitHub CI pipelines (Tom Hu) * Replace `PageRevision` with generic `Revision` model (Sage Abdullah) * Make it possible to reuse and customise Wagtail’s fonts with CSS variables (LB (Ben) Johnston) + * Add better handling and informative developer errors for cross linking URLS (e.g. success after add) in generic views `wagtail.admin.views.generic` (Matt Westcott) * Fix: Typo in `ResumeWorkflowActionFormatter` message (Stefan Hammer) * Fix: Throw a meaningful error when saving an image to an unrecognised image format (Christian Franke) * Fix: Remove extra padding for headers with breadcrumbs on mobile viewport (Steven Steinwand) diff --git a/docs/releases/4.0.md b/docs/releases/4.0.md index 95a0fdc0c2..40c201780f 100644 --- a/docs/releases/4.0.md +++ b/docs/releases/4.0.md @@ -20,6 +20,7 @@ depth: 1 * Use `FormData` instead of jQuery's `form.serialize` when editing documents or images just added so that additional fields can be better supported (Stefan Hammer) * Add informational Codecov status checks for GitHub CI pipelines (Tom Hu) * Make it possible to reuse and customise Wagtail’s fonts with CSS variables (LB (Ben) Johnston) + * Add better handling and informative developer errors for cross linking URLS (e.g. success after add) in generic views `wagtail.admin.views.generic` (Matt Westcott) ### Bug fixes diff --git a/wagtail/admin/templates/wagtailadmin/generic/edit.html b/wagtail/admin/templates/wagtailadmin/generic/edit.html index de19fc4060..a478732bff 100644 --- a/wagtail/admin/templates/wagtailadmin/generic/edit.html +++ b/wagtail/admin/templates/wagtailadmin/generic/edit.html @@ -3,7 +3,7 @@ {% block actions %} - {% if can_delete %} + {% if delete_url %} {{ delete_item_label }} {% endif %} {% endblock %} diff --git a/wagtail/admin/templates/wagtailadmin/generic/index.html b/wagtail/admin/templates/wagtailadmin/generic/index.html index 77adf18f4b..ee0ebdccf4 100644 --- a/wagtail/admin/templates/wagtailadmin/generic/index.html +++ b/wagtail/admin/templates/wagtailadmin/generic/index.html @@ -4,9 +4,8 @@ {% block titletag %}{{ page_title }} {{ page_subtitle }}{% endblock %} {% block content %} - {% if can_add %} - {% url view.add_url_name as add_link %} - {% include "wagtailadmin/shared/header.html" with title=page_title subtitle=page_subtitle action_url=add_link action_text=view.add_item_label icon=header_icon only %} + {% if add_url %} + {% include "wagtailadmin/shared/header.html" with title=page_title subtitle=page_subtitle action_url=add_url action_text=add_item_label icon=header_icon only %} {% else %} {% include "wagtailadmin/shared/header.html" with title=page_title subtitle=page_subtitle icon=header_icon only %} {% endif %} diff --git a/wagtail/admin/views/generic/models.py b/wagtail/admin/views/generic/models.py index 92955169d2..bb5711d0d5 100644 --- a/wagtail/admin/views/generic/models.py +++ b/wagtail/admin/views/generic/models.py @@ -1,4 +1,5 @@ from django import VERSION as DJANGO_VERSION +from django.core.exceptions import ImproperlyConfigured from django.db import transaction from django.forms import Form from django.http import HttpResponseRedirect @@ -62,6 +63,7 @@ class IndexView( model = None index_url_name = None add_url_name = None + add_item_label = _("Add") edit_url_name = None template_name = "wagtailadmin/generic/index.html" context_object_name = None @@ -141,6 +143,10 @@ class IndexView( if self.edit_url_name: return reverse(self.edit_url_name, args=(instance.pk,)) + def get_add_url(self): + if self.add_url_name: + return reverse(self.add_url_name) + def get_valid_orderings(self): orderings = [] for col in self.columns: @@ -169,6 +175,10 @@ class IndexView( self.permission_policy is None or self.permission_policy.user_has_permission(self.request.user, "add") ) + if context["can_add"]: + context["add_url"] = self.get_add_url() + context["add_item_label"] = self.add_item_label + context["table"] = table context["media"] = table.media context["index_url"] = index_url @@ -201,9 +211,19 @@ class CreateView( submit_button_label = gettext_lazy("Create") def get_add_url(self): + if not self.add_url_name: + raise ImproperlyConfigured( + "Subclasses of wagtail.admin.views.generic.models.CreateView must provide an " + "add_url_name attribute or a get_add_url method" + ) return reverse(self.add_url_name) def get_success_url(self): + if not self.index_url_name: + raise ImproperlyConfigured( + "Subclasses of wagtail.admin.views.generic.models.CreateView must provide an " + "index_url_name attribute or a get_success_url method" + ) return reverse(self.index_url_name) def get_success_message(self, instance): @@ -289,12 +309,23 @@ class EditView( return str(self.object) def get_edit_url(self): + if not self.edit_url_name: + raise ImproperlyConfigured( + "Subclasses of wagtail.admin.views.generic.models.EditView must provide an " + "edit_url_name attribute or a get_edit_url method" + ) return reverse(self.edit_url_name, args=(self.object.id,)) def get_delete_url(self): - return reverse(self.delete_url_name, args=(self.object.id,)) + if self.delete_url_name: + return reverse(self.delete_url_name, args=(self.object.id,)) def get_success_url(self): + if not self.index_url_name: + raise ImproperlyConfigured( + "Subclasses of wagtail.admin.views.generic.models.EditView must provide an " + "index_url_name attribute or a get_success_url method" + ) return reverse(self.index_url_name) def save_instance(self): @@ -350,12 +381,13 @@ class EditView( context = super().get_context_data(**kwargs) context["action_url"] = self.get_edit_url() context["submit_button_label"] = self.submit_button_label - context["delete_url"] = self.get_delete_url() - context["delete_item_label"] = self.delete_item_label context["can_delete"] = ( self.permission_policy is None or self.permission_policy.user_has_permission(self.request.user, "delete") ) + if context["can_delete"]: + context["delete_url"] = self.get_delete_url() + context["delete_item_label"] = self.delete_item_label return context @@ -381,12 +413,22 @@ class DeleteView( return super().get_object(queryset) def get_success_url(self): + if not self.index_url_name: + raise ImproperlyConfigured( + "Subclasses of wagtail.admin.views.generic.models.DeleteView must provide an " + "index_url_name attribute or a get_success_url method" + ) return reverse(self.index_url_name) def get_page_subtitle(self): return str(self.object) def get_delete_url(self): + if not self.index_url_name: + raise ImproperlyConfigured( + "Subclasses of wagtail.admin.views.generic.models.DeleteView must provide a " + "delete_url_name attribute or a get_delete_url method" + ) return reverse(self.delete_url_name, args=(self.object.id,)) def get_success_message(self):