summaryrefslogtreecommitdiff
path: root/python-wagtail-headless-preview.spec
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-05 06:08:57 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-05 06:08:57 +0000
commit4910c41a01cf0b820d3be1eed978a19bb1f39e12 (patch)
treeb38e81c8ea1c3ee237c2cb3bdadb74652695784f /python-wagtail-headless-preview.spec
parentefe4a97c4ed65907d36131c5c6561df41d365217 (diff)
automatic import of python-wagtail-headless-previewopeneuler20.03
Diffstat (limited to 'python-wagtail-headless-preview.spec')
-rw-r--r--python-wagtail-headless-preview.spec1047
1 files changed, 1047 insertions, 0 deletions
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/)
+
+[![Build status](https://img.shields.io/github/workflow/status/torchbox/wagtail-headless-preview/CI/main?style=for-the-badge)](https://github.com/torchbox/wagtail-headless-preview/actions)
+[![PyPI](https://img.shields.io/pypi/v/wagtail-headless-preview.svg?style=for-the-badge)](https://pypi.org/project/wagtail-headless-preview/)
+[![black](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)](https://github.com/psf/black)
+[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/torchbox/wagtail-headless-preview/main.svg)](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/)
+
+[![Build status](https://img.shields.io/github/workflow/status/torchbox/wagtail-headless-preview/CI/main?style=for-the-badge)](https://github.com/torchbox/wagtail-headless-preview/actions)
+[![PyPI](https://img.shields.io/pypi/v/wagtail-headless-preview.svg?style=for-the-badge)](https://pypi.org/project/wagtail-headless-preview/)
+[![black](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)](https://github.com/psf/black)
+[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/torchbox/wagtail-headless-preview/main.svg)](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/)
+
+[![Build status](https://img.shields.io/github/workflow/status/torchbox/wagtail-headless-preview/CI/main?style=for-the-badge)](https://github.com/torchbox/wagtail-headless-preview/actions)
+[![PyPI](https://img.shields.io/pypi/v/wagtail-headless-preview.svg?style=for-the-badge)](https://pypi.org/project/wagtail-headless-preview/)
+[![black](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)](https://github.com/psf/black)
+[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/torchbox/wagtail-headless-preview/main.svg)](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