diff --git a/docs/building_your_site/djangodevelopers.rst b/docs/building_your_site/djangodevelopers.rst index e725730893..c240403645 100644 --- a/docs/building_your_site/djangodevelopers.rst +++ b/docs/building_your_site/djangodevelopers.rst @@ -214,7 +214,7 @@ Methods: * get_descendants * get_siblings * search -* show_as_mode +* serve_preview Page Queryset Methods diff --git a/docs/model_recipes.rst b/docs/model_recipes.rst index ae011126a7..e799ef70ab 100644 --- a/docs/model_recipes.rst +++ b/docs/model_recipes.rst @@ -194,7 +194,7 @@ Preview Modes ------------- preview_modes -show_as_mode +serve_preview diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py index 6d6157d33e..a1fb6bdaea 100644 --- a/wagtail/wagtailadmin/views/pages.py +++ b/wagtail/wagtailadmin/views/pages.py @@ -1,3 +1,5 @@ +import warnings + from django.http import Http404, HttpResponse from django.shortcuts import render, redirect, get_object_or_404 from django.core.exceptions import ValidationError, PermissionDenied @@ -396,6 +398,27 @@ def view_draft(request, page_id): return page.serve(request) +def get_preview_response(page, preview_mode): + """ + Helper function for preview_on_edit and preview_on_create - + return a page's preview response via either serve_preview or the deprecated + show_as_mode method + """ + # Check the deprecated Page.show_as_mode method, as subclasses of Page + # might be overriding that to return a response + response = page.show_as_mode(preview_mode) + if response: + warnings.warn( + "Defining 'show_as_mode' on a page model is deprecated. Use 'serve_preview' instead", + DeprecationWarning + ) + return response + else: + # show_as_mode did not return a response, so go ahead and use the 'proper' + # serve_preview method + return page.serve_preview(page.dummy_request(), preview_mode) + + @permission_required('wagtailadmin.access_admin') def preview_on_edit(request, page_id): # Receive the form submission that would typically be posted to the 'edit' view. If submission is valid, @@ -410,7 +433,7 @@ def preview_on_edit(request, page_id): form.save(commit=False) preview_mode = request.GET.get('mode', page.default_preview_mode) - response = page.show_as_mode(preview_mode) + response = get_preview_response(page, preview_mode) response['X-Wagtail-Preview'] = 'ok' return response @@ -455,7 +478,7 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p page.path = Page._get_children_path_interval(parent_page.path)[1] preview_mode = request.GET.get('mode', page.default_preview_mode) - response = page.show_as_mode(preview_mode) + response = get_preview_response(page, preview_mode) response['X-Wagtail-Preview'] = 'ok' return response diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py index 42e132daad..3d69873f9a 100644 --- a/wagtail/wagtailcore/models.py +++ b/wagtail/wagtailcore/models.py @@ -725,15 +725,38 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, Indexed)): def default_preview_mode(self): return self.preview_modes[0][0] + def serve_preview(self, request, mode_name): + """ + Return an HTTP response for use in page previews. Normally this would be equivalent + to self.serve(request), since we obviously want the preview to be indicative of how + it looks on the live site. However, there are a couple of cases where this is not + appropriate, and custom behaviour is required: + + 1) The page has custom routing logic that derives some additional required + args/kwargs to be passed to serve(). The routing mechanism is bypassed when + previewing, so there's no way to know what args we should pass. In such a case, + the page model needs to implement its own version of serve_preview. + + 2) The page has several different renderings that we would like to be able to see + when previewing - for example, a form page might have one rendering that displays + the form, and another rendering to display a landing page when the form is posted. + This can be done by setting a custom preview_modes list on the page model - + Wagtail will allow the user to specify one of those modes when previewing, and + pass the chosen mode_name to serve_preview so that the page model can decide how + to render it appropriately. (Page models that do not specify their own preview_modes + list will always receive an empty string as mode_name.) + + Any templates rendered during this process should use the 'request' object passed + here - this ensures that request.user and other properties are set appropriately for + the wagtail user bar to be displayed. This request will always be a GET. + """ + return self.serve(request) + def show_as_mode(self, mode_name): - """ - Given an internal name from the preview_modes list, return an HTTP response - indicative of the page being viewed in that mode. By default this passes a - dummy request into the serve() mechanism, ensuring that it matches the behaviour - on the front-end; subclasses that define additional page modes will need to - implement alternative logic to serve up the appropriate view here. - """ - return self.serve(self.dummy_request()) + # Deprecated API for rendering previews. If this returns something other than None, + # we know that a subclass of Page has overridden this, and we should try to work with + # that response if possible. + return None def get_cached_paths(self): """ diff --git a/wagtail/wagtailforms/models.py b/wagtail/wagtailforms/models.py index 6bde684ace..79dcaa0e2d 100644 --- a/wagtail/wagtailforms/models.py +++ b/wagtail/wagtailforms/models.py @@ -175,13 +175,13 @@ class AbstractForm(Page): ('landing', 'Landing page'), ] - def show_as_mode(self, mode): + def serve_preview(self, request, mode): if mode == 'landing': - return render(self.dummy_request(), self.landing_page_template, { + return render(request, self.landing_page_template, { 'self': self, }) else: - return super(AbstractForm, self).show_as_mode(mode) + return super(AbstractForm, self).serve_preview(request, mode) class AbstractEmailForm(AbstractForm): diff --git a/wagtail/wagtailforms/tests.py b/wagtail/wagtailforms/tests.py index 38903d2ff9..28df108ab7 100644 --- a/wagtail/wagtailforms/tests.py +++ b/wagtail/wagtailforms/tests.py @@ -61,7 +61,7 @@ class TestPageModes(TestCase): self.form_page = Page.objects.get(url_path='/home/contact-us/').specific def test_form(self): - response = self.form_page.show_as_mode('form') + response = self.form_page.serve_preview(self.form_page.dummy_request(), 'form') # Check response self.assertContains(response, """""") @@ -69,7 +69,7 @@ class TestPageModes(TestCase): self.assertTemplateNotUsed(response, 'tests/form_page_landing.html') def test_landing(self): - response = self.form_page.show_as_mode('landing') + response = self.form_page.serve_preview(self.form_page.dummy_request(), 'landing') # Check response self.assertContains(response, "Thank you for your feedback.")