diff --git a/djangocms_versioning/admin.py b/djangocms_versioning/admin.py index d24262d6..40d7931a 100644 --- a/djangocms_versioning/admin.py +++ b/djangocms_versioning/admin.py @@ -1038,12 +1038,12 @@ def publish_view(self, request, object_id): if not version.can_be_published(): self.message_user(request, _("Version cannot be published"), messages.ERROR) - return redirect(requested_redirect or redirect_url) + return self._internal_redirect(requested_redirect, redirect_url) try: version.check_publish(request.user) except ConditionFailed as e: self.message_user(request, force_str(e), messages.ERROR) - return redirect(requested_redirect or redirect_url) + return self._internal_redirect(requested_redirect, redirect_url) # Publish the version version.publish(request.user) @@ -1054,9 +1054,25 @@ def publish_view(self, request, object_id): # Redirect to published? if conf.ON_PUBLISH_REDIRECT == "published": if hasattr(version.content, "get_absolute_url"): - redirect_url = version.content.get_absolute_url() or redirect_url + requested_redirect = requested_redirect or version.content.get_absolute_url() + + return self._internal_redirect(requested_redirect, redirect_url) + + + def _internal_redirect(self, url, fallback): + """Helper function to check if the give URL is resolvable + If resolvable, return the URL; otherwise, returns the fallback URL. + """ + if not url: + return redirect(fallback) + + try: + resolve(url) + except Resolver404: + return redirect(fallback) + + return redirect(url) - return redirect(requested_redirect or redirect_url) def unpublish_view(self, request, object_id): """Unpublishes the specified version and redirects back to the diff --git a/tests/test_admin.py b/tests/test_admin.py index 2997116a..aeface20 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1384,6 +1384,46 @@ def test_publish_view_redirects_according_to_settings(self): conf.ON_PUBLISH_REDIRECT = original_setting + + def test_publish_resolvable_redirect_url(self): + from djangocms_versioning import conf + + original_setting = conf.ON_PUBLISH_REDIRECT + conf.ON_PUBLISH_REDIRECT = "published" + + user = self.get_superuser() + poll_version = factories.PollVersionFactory(state=constants.DRAFT) + + # when there is no requested redirect + url = self.get_admin_url( + self.versionable.version_model_proxy, "publish", poll_version.pk + ) + + with self.login_user_context(user): + response = self.client.post(url) + + self.assertEqual(poll_version.content.get_absolute_url(), response.url) + + # when the requested url is resolvable + resolvable_url = url + "?next=" + helpers.get_preview_url(poll_version.content) + + with self.login_user_context(user): + response = self.client.post(resolvable_url) + + self.assertEqual(response.url, helpers.get_preview_url(poll_version.content)) + + # when the requested url is not resolvable, should default to version list url + not_resolvable_url = url + "?next=http://example.com" + + with self.login_user_context(user): + response = self.client.post(not_resolvable_url) + + self.assertEqual(response.url, helpers.get_preview_url(poll_version.content)) + + conf.ON_PUBLISH_REDIRECT = original_setting + + + def test_published_view_sets_modified_time(self): poll_version = factories.PollVersionFactory(state=constants.DRAFT) url = self.get_admin_url(