{ "info": { "author": "Matthew Westcott - POC, Karl Hobley", "author_email": "matthew.westcott@torchbox.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Wagtail", "Framework :: Wagtail :: 2", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content" ], "description": "# [Wagtail Headless Preview](https://pypi.org/project/wagtail-headless-preview/) [](https://pypi.org/project/wagtail-headless-preview/)\n\n## Overview\n\nWith 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.\n\nThis package enables previews for Wagtail pages when used in a headless setup by routing the preview to the specified front-end URL.\n\n## Setup\n\nInstall using pip:\n```sh\npip install wagtail-headless-preview\n```\n\nAfter installing the module, add `wagtail_headless_preview` to installed apps in your settings file:\n\n```python\n# settings.py\n\nINSTALLED_APPS = [\n ...\n 'wagtail_headless_preview',\n]\n```\n\nRun migrations:\n\n```sh\n$ ./manage.py migrate\n```\n\nthen configure the preview client URL using the `HEADLESS_PREVIEW_CLIENT_URLS` setting.\n\nFor single site, the configuration should look like:\n\n```python\nHEADLESS_PREVIEW_CLIENT_URLS = {\n 'default': 'http://localhost:8020/',\n}\n```\n\nFor a multi-site setup, add each site as a separate entry:\n\n```python\nHEADLESS_PREVIEW_CLIENT_URLS = {\n 'default': 'http://localhost:8020/',\n 'site1.example.com': 'http://localhost:8020/',\n 'site2.example.com': 'http://localhost:8021/',\n}\n```\n\nOptionally, you can enable live preview functionality with the `HEADLESS_PREVIEW_LIVE` setting:\n\n```python\n# settings.py\nHEADLESS_PREVIEW_LIVE = True\n```\n\nNote: Your front-end app must be set up for live preview, a feature that usually requires [Django Channels](https://github.com/django/channels/) or other WebSocket/async libraries. \n\n## Usage\n\nAdd `HeadlessPreviewMixin` to your page class:\n\n```python\nfrom wagtail_headless_preview.models import HeadlessPreviewMixin\n\nclass MyWonderfulPage(HeadlessPreviewMixin, Page):\n pass\n```\n\n## How will my front-end app display preview content?\n\nThis depends on your project, as it will be dictated by the requirements of your front-end app.\n\nThe following example uses a Wagtail API endpoint to access previews - \nyour app may opt to access page previews using [GraphQL](https://wagtail.io/blog/getting-started-with-wagtail-and-graphql/) instead.\n\n### Example\n\nThis 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.\n\n* Add `wagtail.api.v2` to the installed apps:\n```python\n# settings.py\n\nINSTALLED_APPS = [\n ...\n 'wagtail.api.v2',\n]\n```\n\n* create an `api.py` file in your project directory:\n```python\nfrom django.contrib.contenttypes.models import ContentType\n\nfrom wagtail.api.v2.endpoints import PagesAPIEndpoint\nfrom wagtail.api.v2.router import WagtailAPIRouter\n\nfrom wagtail_headless_preview.models import PagePreview\nfrom rest_framework.response import Response\n\n\n# Create the router. \"wagtailapi\" is the URL namespace\napi_router = WagtailAPIRouter('wagtailapi')\n\n\nclass PagePreviewAPIEndpoint(PagesAPIEndpoint):\n known_query_parameters = PagesAPIEndpoint.known_query_parameters.union(['content_type', 'token'])\n\n def listing_view(self, request):\n page = self.get_object()\n serializer = self.get_serializer(page)\n return Response(serializer.data)\n\n def detail_view(self, request, pk):\n page = self.get_object()\n serializer = self.get_serializer(page)\n return Response(serializer.data)\n\n def get_object(self):\n app_label, model = self.request.GET['content_type'].split('.')\n content_type = ContentType.objects.get(app_label=app_label, model=model)\n\n page_preview = PagePreview.objects.get(content_type=content_type, token=self.request.GET['token'])\n page = page_preview.as_page()\n if not page.pk:\n # fake primary key to stop API URL routing from complaining\n page.pk = 0\n\n return page\n\n\napi_router.register_endpoint('page_preview', PagePreviewAPIEndpoint)\n```\n\n* Register the API URLs so Django can route requests into the API:\n\n```python\n# urls.py\n\nfrom .api import api_router\n\nurlpatterns = [\n ...\n path('api/v2/', api_router.urls),\n ...\n # Ensure that the api_router line appears above the default Wagtail page serving route\n path('', include(wagtail_urls)),\n]\n```\n\nFor 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)\n\n* Next, add a `client/index.html` file in your project root. This will query the API to display our preview:\n\n```html\n\n\n
\n \n\n\n\n```\n\n\n* Install django-cors-headers: `pip install django-cors-headers`\n* Add CORS config to your settings file to allow the front-end to access the API\n\n```python\nCORS_ORIGIN_ALLOW_ALL = True\nCORS_URLS_REGEX = r'^/api/v2/'\n ```\n\nand follow the rest of the [setup instructions for django-cors-headers](https://github.com/ottoyiu/django-cors-headers#setup).\n\n* Start up your site as normal: `./manage.py runserver 0:8000`\n* Serve the front-end `client/index.html` at `http://localhost:8020/`\n - this can be done by running `python3 -m http.server 8020` from inside the client directory\n* From the wagtail admin interface, edit (or create) and preview a page that uses `HeadlessPreviewMixin`\n\nThe preview page should now show you the API response for the preview! \ud83c\udf89\n\nThis is where a real front-end would take over and display the preview as it would be seen on the live site.\n\n## Credits\n\n- Matthew Westcott ([@gasman](https://github.com/gasman)), initial proof of concept\n- Karl Hobley ([@kaedroho](https://github.com/kaedroho)), improvements\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/torchbox/wagtail-headless-preview", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "wagtail-headless-preview", "package_url": "https://pypi.org/project/wagtail-headless-preview/", "platform": "", "project_url": "https://pypi.org/project/wagtail-headless-preview/", "project_urls": { "Homepage": "https://github.com/torchbox/wagtail-headless-preview" }, "release_url": "https://pypi.org/project/wagtail-headless-preview/0.1.4/", "requires_dist": [ "wagtail (>=2.0)", "tox ; extra == 'testing'", "django-cors-headers ; extra == 'testing'" ], "requires_python": "", "summary": "Wagtail previews in headless mode.", "version": "0.1.4" }, "last_serial": 5710376, "releases": { "0.0.2": [ { "comment_text": "", "digests": { "md5": "d55060c4e8195fa6842fca382c04d63b", "sha256": "3146be430967461cab56f76012a08cf05aec8be56e3cce8757fc5f140b3465e2" }, "downloads": -1, "filename": "wagtail_headless_preview-0.0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "d55060c4e8195fa6842fca382c04d63b", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 6101, "upload_time": "2019-05-01T08:52:26", "url": "https://files.pythonhosted.org/packages/8c/3b/cd7ae15dfe9dd59896f8511d8703c6e28348048904f20c856e5d434a6393/wagtail_headless_preview-0.0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "56f5f4d977ea3024fdfd157283c899a1", "sha256": "c2ed9483aab77a550023d1d711136bb5491b4bad7e3d11f1f058e79dc345a5fe" }, "downloads": -1, "filename": "wagtail-headless-preview-0.0.2.tar.gz", "has_sig": false, "md5_digest": "56f5f4d977ea3024fdfd157283c899a1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4707, "upload_time": "2019-05-01T08:52:30", "url": "https://files.pythonhosted.org/packages/9d/9f/6c9e0d6b5039448ca791d4cc96889cf0c158c6af66044047a1cbb447440b/wagtail-headless-preview-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "78e3d483023ce8d172c42570e811e3c6", "sha256": "a10a061f74ba0d322de713dac3f1dc19b8e36e14137d84b7114c8277369911e7" }, "downloads": -1, "filename": "wagtail_headless_preview-0.0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "78e3d483023ce8d172c42570e811e3c6", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 7426, "upload_time": "2019-05-02T11:15:51", "url": "https://files.pythonhosted.org/packages/1d/1e/5a9a687b8bd959f1ca07a78389300b445b2d6061946481f7814a1239ff76/wagtail_headless_preview-0.0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "97112e58bd58c1d1690cbd6554e06dc1", "sha256": "e58b1e0d0eb48ac97ede2338b564683e2ec7527405debae296ead1e02b500dca" }, "downloads": -1, "filename": "wagtail-headless-preview-0.0.3.tar.gz", "has_sig": false, "md5_digest": "97112e58bd58c1d1690cbd6554e06dc1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6301, "upload_time": "2019-05-02T11:37:46", "url": "https://files.pythonhosted.org/packages/af/82/6e94652c668ab3f809066ce00f722a1c7afd287b6a55c80dfc9cfc3fa80a/wagtail-headless-preview-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "5d5e3008dc2c2506d6259fe3fe9247f6", "sha256": "1485c5c9c2f6908debb0696b8dedfb7038b57694a293bce141bc1c91c234053d" }, "downloads": -1, "filename": "wagtail_headless_preview-0.0.4-py2-none-any.whl", "has_sig": false, "md5_digest": "5d5e3008dc2c2506d6259fe3fe9247f6", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 7424, "upload_time": "2019-05-02T12:17:30", "url": "https://files.pythonhosted.org/packages/6d/17/02d6b6bf8a8db1ae8300c51cc92d258f0e2dd29f0f3375210a244b05d558/wagtail_headless_preview-0.0.4-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "747eb2d945e21a44ba1a3a99b3297d4c", "sha256": "810a9c60894fb3278ef65cb05172a32d76d6854f64d4b8f854f506a9498e55fd" }, "downloads": -1, "filename": "wagtail-headless-preview-0.0.4.tar.gz", "has_sig": false, "md5_digest": "747eb2d945e21a44ba1a3a99b3297d4c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6303, "upload_time": "2019-05-02T12:17:31", "url": "https://files.pythonhosted.org/packages/d3/71/55b32bf5417f64f0a91c716b13a71d080ec640479f46858e7885ef53cd56/wagtail-headless-preview-0.0.4.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "834768c48a6bcc6c881f645ddd10de12", "sha256": "2b37fa501f183a01ef85d7f4bfe8cf4b45fe903db0529c108291b3b453069888" }, "downloads": -1, "filename": "wagtail_headless_preview-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "834768c48a6bcc6c881f645ddd10de12", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14183, "upload_time": "2019-08-20T14:45:04", "url": "https://files.pythonhosted.org/packages/74/cd/274a8e955daf69417f0ce66e9f723ba16fe53b64a23eeb6c3f3bf8981545/wagtail_headless_preview-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e38247be6765f5c5976c45849617988b", "sha256": "720f52634312eca64e77f5ffb07346556d25a745458b1bd816400263fb2d8061" }, "downloads": -1, "filename": "wagtail-headless-preview-0.1.0.tar.gz", "has_sig": false, "md5_digest": "e38247be6765f5c5976c45849617988b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12474, "upload_time": "2019-08-20T15:12:25", "url": "https://files.pythonhosted.org/packages/d0/59/ab5279c49168e6cf14d814d437229519026639711cc989f59dd3787e4353/wagtail-headless-preview-0.1.0.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "5c1492cb53b0e62d775322b52f51fdcc", "sha256": "efdc5dadab955a3dafdb8421db3ff3a1ea6a0e4528bf7701b30c1792e6c2c8e5" }, "downloads": -1, "filename": "wagtail_headless_preview-0.1.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "5c1492cb53b0e62d775322b52f51fdcc", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15048, "upload_time": "2019-08-21T10:32:48", "url": "https://files.pythonhosted.org/packages/04/01/c864553d4784e8bd4ab69817e19868ff5cb69576c1a1804823472c4636fb/wagtail_headless_preview-0.1.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "58fb1b376925b3d11c6656119a2611a4", "sha256": "2b0a152894949a495ad46d118fb0ec8b7420617b4c909b58f0d521da575ee6e0" }, "downloads": -1, "filename": "wagtail-headless-preview-0.1.3.tar.gz", "has_sig": false, "md5_digest": "58fb1b376925b3d11c6656119a2611a4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13140, "upload_time": "2019-08-21T10:32:50", "url": "https://files.pythonhosted.org/packages/50/8b/e0a4e32081308e5432ad44999cd57ae2430fecb325e89196327c94ce62d5/wagtail-headless-preview-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "3f69c7b203fd66cd63555eb45d1712cd", "sha256": "782060d1150a33e6c3e5dc7f38498281c0526f3fbd3ae81ab3e1df5c230c4b80" }, "downloads": -1, "filename": "wagtail_headless_preview-0.1.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "3f69c7b203fd66cd63555eb45d1712cd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15056, "upload_time": "2019-08-21T15:25:39", "url": "https://files.pythonhosted.org/packages/bb/ec/05ea1f99d3207faa13df08ff5f71a6d4ab203fedbba0808935f78a15659e/wagtail_headless_preview-0.1.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8663dfabe3dc95b8400328cd72c3cb3b", "sha256": "d1fd0acb4c90468bcfad0a99df11b55defd7fdcdb204ecd4b11052e5f1e10295" }, "downloads": -1, "filename": "wagtail-headless-preview-0.1.4.tar.gz", "has_sig": false, "md5_digest": "8663dfabe3dc95b8400328cd72c3cb3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13446, "upload_time": "2019-08-21T15:25:41", "url": "https://files.pythonhosted.org/packages/f8/c8/9e1b66584e2a3875d15e16021a381d1b97fe456804c64c4dba763df03a1a/wagtail-headless-preview-0.1.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3f69c7b203fd66cd63555eb45d1712cd", "sha256": "782060d1150a33e6c3e5dc7f38498281c0526f3fbd3ae81ab3e1df5c230c4b80" }, "downloads": -1, "filename": "wagtail_headless_preview-0.1.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "3f69c7b203fd66cd63555eb45d1712cd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15056, "upload_time": "2019-08-21T15:25:39", "url": "https://files.pythonhosted.org/packages/bb/ec/05ea1f99d3207faa13df08ff5f71a6d4ab203fedbba0808935f78a15659e/wagtail_headless_preview-0.1.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8663dfabe3dc95b8400328cd72c3cb3b", "sha256": "d1fd0acb4c90468bcfad0a99df11b55defd7fdcdb204ecd4b11052e5f1e10295" }, "downloads": -1, "filename": "wagtail-headless-preview-0.1.4.tar.gz", "has_sig": false, "md5_digest": "8663dfabe3dc95b8400328cd72c3cb3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13446, "upload_time": "2019-08-21T15:25:41", "url": "https://files.pythonhosted.org/packages/f8/c8/9e1b66584e2a3875d15e16021a381d1b97fe456804c64c4dba763df03a1a/wagtail-headless-preview-0.1.4.tar.gz" } ] }