Wagtail previews in headless mode.
Project description
Wagtail Headless Preview
Overview
With Wagtail as the backend, and a separate app for the front-end (for example a single page React app), editors are no longer able to preview their changes. This is because the front-end is no longer within Wagtail's direct control. The preview data therefore needs to be exposed to the front-end app.
This package enables previews for Wagtail pages when used in a headless setup by routing the preview to the specified front-end URL.
Setup
Install using pip:
pip install wagtail-headless-preview
After installing the module, add wagtail_headless_preview
to installed apps in your settings file:
# settings.py
INSTALLED_APPS = [
...
'wagtail_headless_preview',
]
Run migrations:
$ ./manage.py migrate
then configure the preview client URL using the HEADLESS_PREVIEW_CLIENT_URLS
setting.
For single site, the configuration should look like:
HEADLESS_PREVIEW_CLIENT_URLS = {
'default': 'http://localhost:8020/',
}
For a multi-site setup, add each site as a separate entry:
HEADLESS_PREVIEW_CLIENT_URLS = {
'default': 'http://localhost:8020/',
'site1.example.com': 'http://localhost:8020/',
'site2.example.com': 'http://localhost:8021/',
}
Optionally, you can enable live preview functionality with the HEADLESS_PREVIEW_LIVE
setting:
# settings.py
HEADLESS_PREVIEW_LIVE = True
Note: Your front-end app must be set up for live preview, a feature that usually requires Django Channels or other WebSocket/async libraries.
Usage
Add HeadlessPreviewMixin
to your page class:
from wagtail_headless_preview.models import HeadlessPreviewMixin
class MyWonderfulPage(HeadlessPreviewMixin, Page):
pass
How will my front-end app display preview content?
This depends on your project, as it will be dictated by the requirements of your front-end app.
The following example uses a Wagtail API endpoint to access previews - your app may opt to access page previews using GraphQL instead.
Example
This example sets up an API endpoint which will return the preview for a page, and then displays that data on a simplified demo front-end app.
- Add
wagtail.api.v2
to the installed apps:
# settings.py
INSTALLED_APPS = [
...
'wagtail.api.v2',
]
- create an
api.py
file in your project directory:
from django.contrib.contenttypes.models import ContentType
from wagtail.api.v2.endpoints import PagesAPIEndpoint
from wagtail.api.v2.router import WagtailAPIRouter
from wagtail_headless_preview.models import PagePreview
from rest_framework.response import Response
# Create the router. "wagtailapi" is the URL namespace
api_router = WagtailAPIRouter('wagtailapi')
class PagePreviewAPIEndpoint(PagesAPIEndpoint):
known_query_parameters = PagesAPIEndpoint.known_query_parameters.union(['content_type', 'token'])
def listing_view(self, request):
page = self.get_object()
serializer = self.get_serializer(page)
return Response(serializer.data)
def detail_view(self, request, pk):
page = self.get_object()
serializer = self.get_serializer(page)
return Response(serializer.data)
def get_object(self):
app_label, model = self.request.GET['content_type'].split('.')
content_type = ContentType.objects.get(app_label=app_label, model=model)
page_preview = PagePreview.objects.get(content_type=content_type, token=self.request.GET['token'])
page = page_preview.as_page()
if not page.pk:
# fake primary key to stop API URL routing from complaining
page.pk = 0
return page
api_router.register_endpoint('page_preview', PagePreviewAPIEndpoint)
- Register the API URLs so Django can route requests into the API:
# urls.py
from .api import api_router
urlpatterns = [
...
path('api/v2/', api_router.urls),
...
# Ensure that the api_router line appears above the default Wagtail page serving route
path('', include(wagtail_urls)),
]
For further information about configuring the wagtail API, refer to the Wagtail API v2 Configuration Guide
- Next, add a
client/index.html
file in your project root. This will query the API to display our preview:
<!DOCTYPE html>
<html>
<head>
<script>
function go() {
var querystring = window.location.search.replace(/^\?/, '');
var params = {};
querystring.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) {
params[decodeURIComponent(key)] = decodeURIComponent(value);
});
var apiUrl = 'http://localhost:8000/api/v2/page_preview/1/?content_type=' + encodeURIComponent(params['content_type']) + '&token=' + encodeURIComponent(params['token']) + '&format=json';
fetch(apiUrl).then(function(response) {
response.text().then(function(text) {
document.body.innerText = text;
});
});
}
</script>
</head>
<body onload="go()"></body>
</html>
- Install django-cors-headers:
pip install django-cors-headers
- Add CORS config to your settings file to allow the front-end to access the API
CORS_ORIGIN_ALLOW_ALL = True
CORS_URLS_REGEX = r'^/api/v2/'
and follow the rest of the setup instructions for django-cors-headers.
- Start up your site as normal:
./manage.py runserver 0:8000
- Serve the front-end
client/index.html
athttp://localhost:8020/
- this can be done by running
python3 -m http.server 8020
from inside the client directory
- this can be done by running
- From the wagtail admin interface, edit (or create) and preview a page that uses
HeadlessPreviewMixin
The preview page should now show you the API response for the preview! 🎉
This is where a real front-end would take over and display the preview as it would be seen on the live site.
Credits
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for wagtail-headless-preview-0.1.4.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | d1fd0acb4c90468bcfad0a99df11b55defd7fdcdb204ecd4b11052e5f1e10295 |
|
MD5 | 8663dfabe3dc95b8400328cd72c3cb3b |
|
BLAKE2b-256 | f8c89e1b66584e2a3875d15e16021a381d1b97fe456804c64c4dba763df03a1a |
Hashes for wagtail_headless_preview-0.1.4-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 782060d1150a33e6c3e5dc7f38498281c0526f3fbd3ae81ab3e1df5c230c4b80 |
|
MD5 | 3f69c7b203fd66cd63555eb45d1712cd |
|
BLAKE2b-256 | bbec05ea1f99d3207faa13df08ff5f71a6d4ab203fedbba0808935f78a15659e |