diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-05-05 06:08:57 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-05-05 06:08:57 +0000 |
| commit | 4910c41a01cf0b820d3be1eed978a19bb1f39e12 (patch) | |
| tree | b38e81c8ea1c3ee237c2cb3bdadb74652695784f | |
| parent | efe4a97c4ed65907d36131c5c6561df41d365217 (diff) | |
automatic import of python-wagtail-headless-previewopeneuler20.03
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-wagtail-headless-preview.spec | 1047 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 1049 insertions, 0 deletions
@@ -0,0 +1 @@ +/wagtail-headless-preview-0.5.0.tar.gz diff --git a/python-wagtail-headless-preview.spec b/python-wagtail-headless-preview.spec new file mode 100644 index 0000000..798fab9 --- /dev/null +++ b/python-wagtail-headless-preview.spec @@ -0,0 +1,1047 @@ +%global _empty_manifest_terminate_build 0 +Name: python-wagtail-headless-preview +Version: 0.5.0 +Release: 1 +Summary: Enhance Wagtail previews in headless setups. +License: BSD +URL: https://github.com/torchbox/wagtail-headless-preview +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/e5/43/4aeaec414f2aba3190db4e342943c6557681f7c1081ee21ad5cf574f3b84/wagtail-headless-preview-0.5.0.tar.gz +BuildArch: noarch + +Requires: python3-wagtail +Requires: python3-tox +Requires: python3-django-cors-headers + +%description +# [Wagtail Headless Preview](https://pypi.org/project/wagtail-headless-preview/) + +[](https://github.com/torchbox/wagtail-headless-preview/actions) +[](https://pypi.org/project/wagtail-headless-preview/) +[](https://github.com/psf/black) +[](https://results.pre-commit.ci/latest/github/torchbox/wagtail-headless-preview/main) + + +## 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: +```sh +pip install wagtail-headless-preview +``` + +After installing the module, add `wagtail_headless_preview` to installed apps in your settings file: + +```python +# settings.py + +INSTALLED_APPS = [ + # ... + "wagtail_headless_preview", +] +``` + +Run migrations: + +```sh +$ python manage.py migrate +``` + +Then configure the preview client URL using the `CLIENT_URLS` option in the `WAGTAIL_HEADLESS_PREVIEW` setting. + +## Configuration + +`wagtail_headless_preview` uses a single settings dictionary: + +```python +# settings.py + +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": {}, # defaults to an empty dict. You must at the very least define the default client URL. + "SERVE_BASE_URL": None, # can be used for HeadlessServeMixin + "REDIRECT_ON_PREVIEW": False, # set to True to redirect to the preview instead of using the Wagtail default mechanism + "ENFORCE_TRAILING_SLASH": True, # set to False in order to disable the trailing slash enforcement +} +``` + +### Single site setup + +For single sites, add the front-end URL as the default entry: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "http://localhost:8020", + } +} +``` + +If you have configured your Wagtail `Site` entry to use the front-end URL, then you can update your configuration to: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "{SITE_ROOT_URL}", + } +} +``` + +The `{SITE_ROOT_URL}` placeholder is replaced with the `root_url` property of the `Site` the preview page belongs to. + + +### Multi-site setup + +For a multi-site setup, add each site as a separate entry in the `CLIENT_URLS` option in the `WAGTAIL_HEADLESS_PREVIEW` setting: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "https://wagtail.org", # adjust to match your front-end URL. e.g. locally it may be something like http://localhost:8020 + "cms.wagtail.org": "https://wagtail.org", + "cms.torchbox.com": "http://torchbox.com", + }, + # ... +} +``` + +### Serve URL + +To make the editing experience seamles and to avoid server errors due to missing templates, +you can use the `HeadlessMixin` which combines the `HeadlessServeMixin` and `HeadlessPreviewMixin` mixins. + +`HeadlessServeMixin` overrides the Wagtail `Page.serve` method to redirect to the client URL. By default, +it uses the hosts defined in `CLIENT_URLS`. However, you can provide a single URL to rule them all: + +```python +# settings.py + +WAGTAIL_HEADLESS_PREVIEW = { + # ... + "SERVE_BASE_URL": "https://my.headless.site", +} +``` + +### Enforce trailing slash + +By default, `wagtail_headless_preview` enforces a trailing slash on the client URL. You can disable this behaviour by +setting `ENFORCE_TRAILING_SLASH` to `False`: + +```python +# settings.py +WAGTAIL_HEADLESS_PREVIEW = { + # ... + "ENFORCE_TRAILING_SLASH": False +} +``` + +## Usage + +To enable preview as well as wire in the "View live" button in the Wagtail UI, add the `HeadlessMixin` +to your `Page` class: + +```python +from wagtail_headless_preview.models import HeadlessMixin + + +class MyWonderfulPage(HeadlessMixin, Page): + pass +``` + +If you require more granular control, or if you've modified you `Page` model's `serve` method, you can +add `HeadlessPreviewMixin` to your `Page` class to only handle previews: + +```python +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](https://wagtail.io/blog/getting-started-with-wagtail-and-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: +```python +# settings.py + +INSTALLED_APPS = [ + # ... + "wagtail.api.v2", +] +``` + +* create an `api.py` file in your project directory: + +```python +from django.contrib.contenttypes.models import ContentType + +from wagtail.api.v2.router import WagtailAPIRouter +from wagtail.api.v2.views import PagesAPIViewSet + +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 PagePreviewAPIViewSet(PagesAPIViewSet): + known_query_parameters = PagesAPIViewSet.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", PagePreviewAPIViewSet) +``` + +* Register the API URLs so Django can route requests into the API: + +```python +# 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](https://docs.wagtail.io/en/stable/advanced_topics/api/v2/configuration.html) + +* Next, add a `client/index.html` file in your project root. This will query the API to display our preview: + +```html +<!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](https://pypi.org/project/django-cors-headers/): `pip install django-cors-headers` +* Add CORS config to your settings file to allow the front-end to access the API + +```python +# settings.py +CORS_ORIGIN_ALLOW_ALL = True +CORS_URLS_REGEX = r"^/api/v2/" +``` + +and follow the rest of the [setup instructions for django-cors-headers](https://github.com/ottoyiu/django-cors-headers#setup). + +* Start up your site as normal: `python manage.py runserver 0:8000` +* Serve the front-end `client/index.html` at `http://localhost:8020/` + - this can be done by running `python3 -m http.server 8020` from inside the client directory +* 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. + +## Contributing + +All contributions are welcome! + +Note that this project uses [pre-commit](https://github.com/pre-commit/pre-commit). To set up locally: + +```shell +# if you don't have it yet +$ pip install pre-commit +# go to the project directory +$ cd wagtail-headless-preview +# initialize pre-commit +$ pre-commit install + +# Optional, run all checks once for this, then the checks will run only on the changed files +$ pre-commit run --all-files +``` + +### How to run tests + +Now you can run tests as shown below: + +```sh +tox -p +``` + +or, you can run them for a specific environment `tox -e py39-django3.2-wagtail2.15` or specific test +`tox -e py310-django3.2-wagtail2.15 wagtail_headless_preview.tests.test_frontend.TestFrontendViews.test_redirect_on_preview` + +## Credits + +- Matthew Westcott ([@gasman](https://github.com/gasman)), initial proof of concept +- Karl Hobley ([@kaedroho](https://github.com/kaedroho)), PoC improvements + + + + +%package -n python3-wagtail-headless-preview +Summary: Enhance Wagtail previews in headless setups. +Provides: python-wagtail-headless-preview +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-wagtail-headless-preview +# [Wagtail Headless Preview](https://pypi.org/project/wagtail-headless-preview/) + +[](https://github.com/torchbox/wagtail-headless-preview/actions) +[](https://pypi.org/project/wagtail-headless-preview/) +[](https://github.com/psf/black) +[](https://results.pre-commit.ci/latest/github/torchbox/wagtail-headless-preview/main) + + +## 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: +```sh +pip install wagtail-headless-preview +``` + +After installing the module, add `wagtail_headless_preview` to installed apps in your settings file: + +```python +# settings.py + +INSTALLED_APPS = [ + # ... + "wagtail_headless_preview", +] +``` + +Run migrations: + +```sh +$ python manage.py migrate +``` + +Then configure the preview client URL using the `CLIENT_URLS` option in the `WAGTAIL_HEADLESS_PREVIEW` setting. + +## Configuration + +`wagtail_headless_preview` uses a single settings dictionary: + +```python +# settings.py + +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": {}, # defaults to an empty dict. You must at the very least define the default client URL. + "SERVE_BASE_URL": None, # can be used for HeadlessServeMixin + "REDIRECT_ON_PREVIEW": False, # set to True to redirect to the preview instead of using the Wagtail default mechanism + "ENFORCE_TRAILING_SLASH": True, # set to False in order to disable the trailing slash enforcement +} +``` + +### Single site setup + +For single sites, add the front-end URL as the default entry: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "http://localhost:8020", + } +} +``` + +If you have configured your Wagtail `Site` entry to use the front-end URL, then you can update your configuration to: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "{SITE_ROOT_URL}", + } +} +``` + +The `{SITE_ROOT_URL}` placeholder is replaced with the `root_url` property of the `Site` the preview page belongs to. + + +### Multi-site setup + +For a multi-site setup, add each site as a separate entry in the `CLIENT_URLS` option in the `WAGTAIL_HEADLESS_PREVIEW` setting: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "https://wagtail.org", # adjust to match your front-end URL. e.g. locally it may be something like http://localhost:8020 + "cms.wagtail.org": "https://wagtail.org", + "cms.torchbox.com": "http://torchbox.com", + }, + # ... +} +``` + +### Serve URL + +To make the editing experience seamles and to avoid server errors due to missing templates, +you can use the `HeadlessMixin` which combines the `HeadlessServeMixin` and `HeadlessPreviewMixin` mixins. + +`HeadlessServeMixin` overrides the Wagtail `Page.serve` method to redirect to the client URL. By default, +it uses the hosts defined in `CLIENT_URLS`. However, you can provide a single URL to rule them all: + +```python +# settings.py + +WAGTAIL_HEADLESS_PREVIEW = { + # ... + "SERVE_BASE_URL": "https://my.headless.site", +} +``` + +### Enforce trailing slash + +By default, `wagtail_headless_preview` enforces a trailing slash on the client URL. You can disable this behaviour by +setting `ENFORCE_TRAILING_SLASH` to `False`: + +```python +# settings.py +WAGTAIL_HEADLESS_PREVIEW = { + # ... + "ENFORCE_TRAILING_SLASH": False +} +``` + +## Usage + +To enable preview as well as wire in the "View live" button in the Wagtail UI, add the `HeadlessMixin` +to your `Page` class: + +```python +from wagtail_headless_preview.models import HeadlessMixin + + +class MyWonderfulPage(HeadlessMixin, Page): + pass +``` + +If you require more granular control, or if you've modified you `Page` model's `serve` method, you can +add `HeadlessPreviewMixin` to your `Page` class to only handle previews: + +```python +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](https://wagtail.io/blog/getting-started-with-wagtail-and-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: +```python +# settings.py + +INSTALLED_APPS = [ + # ... + "wagtail.api.v2", +] +``` + +* create an `api.py` file in your project directory: + +```python +from django.contrib.contenttypes.models import ContentType + +from wagtail.api.v2.router import WagtailAPIRouter +from wagtail.api.v2.views import PagesAPIViewSet + +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 PagePreviewAPIViewSet(PagesAPIViewSet): + known_query_parameters = PagesAPIViewSet.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", PagePreviewAPIViewSet) +``` + +* Register the API URLs so Django can route requests into the API: + +```python +# 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](https://docs.wagtail.io/en/stable/advanced_topics/api/v2/configuration.html) + +* Next, add a `client/index.html` file in your project root. This will query the API to display our preview: + +```html +<!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](https://pypi.org/project/django-cors-headers/): `pip install django-cors-headers` +* Add CORS config to your settings file to allow the front-end to access the API + +```python +# settings.py +CORS_ORIGIN_ALLOW_ALL = True +CORS_URLS_REGEX = r"^/api/v2/" +``` + +and follow the rest of the [setup instructions for django-cors-headers](https://github.com/ottoyiu/django-cors-headers#setup). + +* Start up your site as normal: `python manage.py runserver 0:8000` +* Serve the front-end `client/index.html` at `http://localhost:8020/` + - this can be done by running `python3 -m http.server 8020` from inside the client directory +* 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. + +## Contributing + +All contributions are welcome! + +Note that this project uses [pre-commit](https://github.com/pre-commit/pre-commit). To set up locally: + +```shell +# if you don't have it yet +$ pip install pre-commit +# go to the project directory +$ cd wagtail-headless-preview +# initialize pre-commit +$ pre-commit install + +# Optional, run all checks once for this, then the checks will run only on the changed files +$ pre-commit run --all-files +``` + +### How to run tests + +Now you can run tests as shown below: + +```sh +tox -p +``` + +or, you can run them for a specific environment `tox -e py39-django3.2-wagtail2.15` or specific test +`tox -e py310-django3.2-wagtail2.15 wagtail_headless_preview.tests.test_frontend.TestFrontendViews.test_redirect_on_preview` + +## Credits + +- Matthew Westcott ([@gasman](https://github.com/gasman)), initial proof of concept +- Karl Hobley ([@kaedroho](https://github.com/kaedroho)), PoC improvements + + + + +%package help +Summary: Development documents and examples for wagtail-headless-preview +Provides: python3-wagtail-headless-preview-doc +%description help +# [Wagtail Headless Preview](https://pypi.org/project/wagtail-headless-preview/) + +[](https://github.com/torchbox/wagtail-headless-preview/actions) +[](https://pypi.org/project/wagtail-headless-preview/) +[](https://github.com/psf/black) +[](https://results.pre-commit.ci/latest/github/torchbox/wagtail-headless-preview/main) + + +## 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: +```sh +pip install wagtail-headless-preview +``` + +After installing the module, add `wagtail_headless_preview` to installed apps in your settings file: + +```python +# settings.py + +INSTALLED_APPS = [ + # ... + "wagtail_headless_preview", +] +``` + +Run migrations: + +```sh +$ python manage.py migrate +``` + +Then configure the preview client URL using the `CLIENT_URLS` option in the `WAGTAIL_HEADLESS_PREVIEW` setting. + +## Configuration + +`wagtail_headless_preview` uses a single settings dictionary: + +```python +# settings.py + +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": {}, # defaults to an empty dict. You must at the very least define the default client URL. + "SERVE_BASE_URL": None, # can be used for HeadlessServeMixin + "REDIRECT_ON_PREVIEW": False, # set to True to redirect to the preview instead of using the Wagtail default mechanism + "ENFORCE_TRAILING_SLASH": True, # set to False in order to disable the trailing slash enforcement +} +``` + +### Single site setup + +For single sites, add the front-end URL as the default entry: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "http://localhost:8020", + } +} +``` + +If you have configured your Wagtail `Site` entry to use the front-end URL, then you can update your configuration to: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "{SITE_ROOT_URL}", + } +} +``` + +The `{SITE_ROOT_URL}` placeholder is replaced with the `root_url` property of the `Site` the preview page belongs to. + + +### Multi-site setup + +For a multi-site setup, add each site as a separate entry in the `CLIENT_URLS` option in the `WAGTAIL_HEADLESS_PREVIEW` setting: + +```python +WAGTAIL_HEADLESS_PREVIEW = { + "CLIENT_URLS": { + "default": "https://wagtail.org", # adjust to match your front-end URL. e.g. locally it may be something like http://localhost:8020 + "cms.wagtail.org": "https://wagtail.org", + "cms.torchbox.com": "http://torchbox.com", + }, + # ... +} +``` + +### Serve URL + +To make the editing experience seamles and to avoid server errors due to missing templates, +you can use the `HeadlessMixin` which combines the `HeadlessServeMixin` and `HeadlessPreviewMixin` mixins. + +`HeadlessServeMixin` overrides the Wagtail `Page.serve` method to redirect to the client URL. By default, +it uses the hosts defined in `CLIENT_URLS`. However, you can provide a single URL to rule them all: + +```python +# settings.py + +WAGTAIL_HEADLESS_PREVIEW = { + # ... + "SERVE_BASE_URL": "https://my.headless.site", +} +``` + +### Enforce trailing slash + +By default, `wagtail_headless_preview` enforces a trailing slash on the client URL. You can disable this behaviour by +setting `ENFORCE_TRAILING_SLASH` to `False`: + +```python +# settings.py +WAGTAIL_HEADLESS_PREVIEW = { + # ... + "ENFORCE_TRAILING_SLASH": False +} +``` + +## Usage + +To enable preview as well as wire in the "View live" button in the Wagtail UI, add the `HeadlessMixin` +to your `Page` class: + +```python +from wagtail_headless_preview.models import HeadlessMixin + + +class MyWonderfulPage(HeadlessMixin, Page): + pass +``` + +If you require more granular control, or if you've modified you `Page` model's `serve` method, you can +add `HeadlessPreviewMixin` to your `Page` class to only handle previews: + +```python +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](https://wagtail.io/blog/getting-started-with-wagtail-and-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: +```python +# settings.py + +INSTALLED_APPS = [ + # ... + "wagtail.api.v2", +] +``` + +* create an `api.py` file in your project directory: + +```python +from django.contrib.contenttypes.models import ContentType + +from wagtail.api.v2.router import WagtailAPIRouter +from wagtail.api.v2.views import PagesAPIViewSet + +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 PagePreviewAPIViewSet(PagesAPIViewSet): + known_query_parameters = PagesAPIViewSet.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", PagePreviewAPIViewSet) +``` + +* Register the API URLs so Django can route requests into the API: + +```python +# 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](https://docs.wagtail.io/en/stable/advanced_topics/api/v2/configuration.html) + +* Next, add a `client/index.html` file in your project root. This will query the API to display our preview: + +```html +<!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](https://pypi.org/project/django-cors-headers/): `pip install django-cors-headers` +* Add CORS config to your settings file to allow the front-end to access the API + +```python +# settings.py +CORS_ORIGIN_ALLOW_ALL = True +CORS_URLS_REGEX = r"^/api/v2/" +``` + +and follow the rest of the [setup instructions for django-cors-headers](https://github.com/ottoyiu/django-cors-headers#setup). + +* Start up your site as normal: `python manage.py runserver 0:8000` +* Serve the front-end `client/index.html` at `http://localhost:8020/` + - this can be done by running `python3 -m http.server 8020` from inside the client directory +* 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. + +## Contributing + +All contributions are welcome! + +Note that this project uses [pre-commit](https://github.com/pre-commit/pre-commit). To set up locally: + +```shell +# if you don't have it yet +$ pip install pre-commit +# go to the project directory +$ cd wagtail-headless-preview +# initialize pre-commit +$ pre-commit install + +# Optional, run all checks once for this, then the checks will run only on the changed files +$ pre-commit run --all-files +``` + +### How to run tests + +Now you can run tests as shown below: + +```sh +tox -p +``` + +or, you can run them for a specific environment `tox -e py39-django3.2-wagtail2.15` or specific test +`tox -e py310-django3.2-wagtail2.15 wagtail_headless_preview.tests.test_frontend.TestFrontendViews.test_redirect_on_preview` + +## Credits + +- Matthew Westcott ([@gasman](https://github.com/gasman)), initial proof of concept +- Karl Hobley ([@kaedroho](https://github.com/kaedroho)), PoC improvements + + + + +%prep +%autosetup -n wagtail-headless-preview-0.5.0 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-wagtail-headless-preview -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Fri May 05 2023 Python_Bot <Python_Bot@openeuler.org> - 0.5.0-1 +- Package Spec generated @@ -0,0 +1 @@ +8f2bf4894570d7fd82be0cf0728c4b69 wagtail-headless-preview-0.5.0.tar.gz |
