Skip to main content
Build Status

wagtail-sharing

Easier sharing of Wagtail drafts.

Wagtail Sharing makes it easier to share Wagtail draft content for review by users who don’t have access to the Wagtail admin site. It allows you to define an alternate hostname and/or port on which to expose the latest revision of all of your Wagtail pages.

For example, let’s say your Wagtail site is running on http://mysite.com. You’ve created a draft page at slug /path/to/draft, but haven’t yet published it. Wagtail Sharing lets you expose that draft page at some other domain, for example http://sharing.mysite.com/path/to/draft.

In another use case, you might have a published page at http://mysite.com/already/published/page, and you’ve made some draft changes. Wagtail Sharing lets you expose those draft changes at http://sharing.mysite.com/already/published/page while still keeping the same published content at your regular domain.

These examples obviously work best when you have some method of restricting access to http://sharing.mysite.com, for example by only exposing that subdomain on a private network.

Wagtail Sharing lets you create separate sharing sites for each Wagtail Site you have defined. It also supports a configurable visual banner on shared pages to remind reviewers that content may differ from your published site.

This new logic only applies to GET requests. Other HTTP methods like POST defer to standard Wagtail handling.

Routing configuration

Wagtail Sharing supports different routing strategies for determining how draft pages are shared.

Database-based routing (default)

The default routing strategy uses sharing sites stored in the database, using a new wagtailsharing.SharingSite model. This approach allows for configuration of different sharing domains for different Wagtail sites.

WAGTAILSHARING_ROUTER = "wagtailsharing.routers.db.DatabaseHostRouter"

With database-based routing, Wagtail adds a new admin section under Settings -> Sharing Sites that allows users to define how they would like to expose latest page revisions.

Sharing sites

No sharing sites exist by default. A sharing site must be manually created for each Wagtail Site to make its latest revisions shareable. Each sharing site is defined by a unique hostname and port number.

In the above configuration, drafts will be viewable at http://sharing.mysite.com:8000/.

Settings-based routing

Sharing can also be configured via Django settings. This approach avoids the need to configure sharing via the database, but only works for the default Wagtail site.

WAGTAILSHARING_ROUTER = "wagtailsharing.routers.settings.SettingsHostRouter"
WAGTAILSHARING_HOST = "http://sharing.mysite.com:8000"

With this configuration, draft pages will also be viewable at http://sharing.mysite.com:8000/.

Specify multiple hosts as a list or comma-delimited string to share the default Wagtail site on multiple domains:

WAGTAILSHARING_ROUTER = "wagtailsharing.routers.settings.SettingsHostRouter"
WAGTAILSHARING_HOST = [
    "http://sharing.mysite.com:8000",
    "http://sharing2.mysite.com:8000",
]

Custom routing

A custom router can be used for alternative routing strategies. For example, you might want to route based on authentication tokens, query parameters, or other criteria beyond hostname matching.

To create a custom router, inherit from wagtailsharing.routers.base.RouterBase and implement the required methods:

from wagtailsharing.routers.base import RouterBase

class CustomRouter(RouterBase):
    def route(self, request, path):
        # Returns (Site, path) tuple or (None, path) if no match.
        ...

    def get_sharing_url(self, page):
        # Returns the sharing URL for a given page.
        ...

Then configure it in your settings:

WAGTAILSHARING_ROUTER = "myapp.routers.CustomRouter"

Setup

Install the package using pip:

$ pip install wagtail-sharing

Add wagtailsharing as an installed app in your Django settings:

# in settings.py
INSTALLED_APPS = (
    ...
    "wagtailsharing",
    ...
)

Replace use of Wagtail’s catch-all URL pattern:

# in urls.py
-from wagtail import urls as wagtail_urls
+from wagtailsharing import urls as wagtailsharing_urls

...

-urlpatterns.append(url(r"", include(wagtail_urls)))
+urlpatterns.append(url(r"", include(wagtailsharing_urls)))

Database-based routing

If you’re using the default database-based routing, you’ll also need to add wagtail.snippets to your installed apps:

# in settings.py
INSTALLED_APPS = (
    ...
    "wagtail.snippets",
    "wagtailsharing",
    ...
)

You’ll also need to run migrations to create the required database tables:

$ python manage.py migrate wagtailsharing

Settings-based routing

If you’re using settings-based routing, you only need to add the router configuration to your settings:

WAGTAILSHARING_ROUTER = "wagtailsharing.routers.settings.SettingsHostRouter"
WAGTAILSHARING_HOST = "http://sharing.mysite.com:8000"

Banners

Pages viewed on a Wagtail Sharing shared site have a simple banner added to them to remind reviewers that the current published content may differ from the content they are viewing.

Banner

This behavior can be disabled by setting settings.WAGTAILSHARING_BANNER = False. The banner template can be overridden by providing an alternate template file at wagtailsharing/banner.html similar to how wagtailadmin template overrides are supported.

Hooks

As with normal page serving, the serving of shared pages continues to respect Wagtail’s built-in before_serve_page hook.

This project adds these additional hooks:

before_route_page

Called when routing, before a page’s route() method is called. This hook is passed the request and the page that will have route() called on it. If the callable returns an HttpResponse, that response will be returned immediately to the user.

This hook allows for any necessary customization of Wagtail’s built-in routing behavior, for example to support ShareableRoutablePageMixin.

before_serve_shared_page

Called before the latest revision of the page is about to be served, just before its serve() method is called. Like before_serve_page this hook is passed the page object, the request object, and the args and kwargs that will be passed to the page’s serve() method. If the callable returns an HttpResponse, that response will be returned immediately to the user.

This hook could be useful for limiting sharing to only certain page types or for modifying a page’s contents when it is shared.

from wagtail import hooks

@hooks.register("before_serve_shared_page")
def modify_shared_title(page, request, args, kwargs):
    page.title += " (Shared)"

after_serve_shared_page

Called after the page’s serve() method is called but before the response is returned to the user. This hook is passed the page object and the response object returned by serve(). If the callable returns an HttpResponse, that response will be returned immediately to the user.

This hook could be useful for directly modifying the response content, for example by adding custom headers or altering the generated HTML. This hook is used to implement the notification banner described above.

from wagtail import hooks

@hooks.register("after_serve_shared_page")
def add_custom_header(page, response):
    response["Wagtail-Is-Shared"] = "1"

Mixins

ShareableRoutablePageMixin

Wagtail’s RoutablePageMixin is not compatible with Wagtail Sharing, instead you need to use ShareableRoutablePageMixin in order to view shared draft content fields on routable pages.

ShareableRoutablePageMixin is used exactly the same way as RoutablePageMixin:

from wagtail.fields import RichTextField
from wagtail.models import Page
from wagtail.contrib.routable_page.models import route
from wagtailsharing.models import ShareableRoutablePageMixin


class EventIndexPage(ShareableRoutablePageMixin, Page):
    intro = RichTextField()

    @route(r"^$")
    def current_events(self, request):
        # …

    @route(r"^past/$")
    def past_events(self, request):
        # …

Compatibility

This project has been tested for compatibility with:

  • Python 3.13 – 3.14

  • Django 5.2 (LTS) – 6.0

  • Wagtail 7.0 (LTS) – 7.4 (LTS)

It should be compatible with all intermediate versions, as well. If you find that it is not, please file an issue.

See past releases for older Python/Django/Wagtail support.

Testing

Running project unit tests requires tox:

$ tox

To run the test app interactively, run:

$ tox -e interactive

Now you can visit http://localhost:8000/admin/ in a browser and log in with admin / changeme.

Open source licensing info

  1. TERMS

  2. LICENSE

  3. CFPB Source Code Policy

Metadata

Release files for wagtail-sharing 2.17

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wagtail-sharing 2.17
File Size Uploaded
wagtail_sharing-2.17.tar.gz 171.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wagtail-sharing 2.17
File Interpreter ABI Platform
wagtail_sharing-2.17-py3-none-any.whl Python 3 none any Details

Total release size: 202.9 kB

Release files / wagtail_sharing-2.17.tar.gz

Download URL wagtail_sharing-2.17.tar.gz
Size 171.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e6135477ae6d6ff988e42ac193ed502a21951ec3c325e3cbdd3e7da3a84d14e4
BLAKE2b-256 checksum
How to use checksums
6d2b96d330130f8549e8244784c9aade8da6b1f1e96f570399809fb86e0e8d5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / wagtail_sharing-2.17-py3-none-any.whl

Download URL wagtail_sharing-2.17-py3-none-any.whl
Size 31.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f034c80400a03b18750f7d7cf3d10661c6c60fde032c898b1c8fa855463a7e67
BLAKE2b-256 checksum
How to use checksums
2bfbd16af91bec1fb70ac7e594e14626e2a0f873bec7b596a645760fb43859e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.17 This release

2 release files

2.16

2 release files

2.15

2 release files

2.14

2 release files

2.13

2 release files

2.12

2 release files

2.11

2 release files

2.10

2 release files

2.9

2 release files

2.8

2 release files

2.7

2 release files

2.6

2 release files

2.5.1

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.1

2 release files

2.2

2 release files

2.1

2 release files

1.0

2 release files

0.8

2 release files

0.7

2 release files

0.6.1

2 release files

0.6

2 release files

0.5.1

1 release file

0.5

1 release file

0.4

1 release file

0.3

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page