[Django]-Wagtail: Can i use the API for fetching read-only drafts of pages for review?

9👍

The API is designed to only serve the live version of pages, to avoid leaking information that isn’t intended to be public. However, you can override this behaviour by subclassing PagesAPIEndpoint – for example:

from django.http import Http404
from rest_framework.response import Response
from wagtail.api.v2.endpoints import PagesAPIEndpoint


class DraftPagesAPIEndpoint(PagesAPIEndpoint):
    def detail_view(self, request, pk):
        instance = self.get_object()

        if request.GET.get('draft'):
            instance = instance.get_latest_revision_as_page()
        elif not instance.live:
            raise Http404

        serializer = self.get_serializer(instance)
        return Response(serializer.data)

Then, when registering URL endpoints, use this class in place of PagesAPIEndpoint:

api_router.register_endpoint('pages', DraftPagesAPIEndpoint)

This will give you the ability to pass ?draft=true in the URL to get back a draft version.

👤gasman

0👍

I tried to implement what @gasman stated in his answer and also what Bufke mentioned in the comment but I couldn’t make it work. I always got Page not found an error when I tried to serialize my instance although the instance was already there.

Further inspection showed that I also needed to override the get_queryset method of PagesAPIEndopint since it excludes the pages that are not live and thus the serializer throws 404.

So, the final changes would be like this:

from django.http import Http404
from rest_framework.response import Response
from wagtail.api.v2.endpoints import PagesAPIEndpoint
from wagtail.api.v2.utils import (
    page_models_from_string,
    BadRequestError,
    filter_page_type,
)


class DraftPagesAPIEndpoint(PagesAPIEndpoint):
    def detail_view(self, request, pk):
        instance = self.get_object()

        if request.GET.get('draft'):
            instance = instance.get_latest_revision_as_page()
        elif not instance.live:
            raise Http404

        serializer = self.get_serializer(instance)
        return Response(serializer.data)

    def get_queryset(self):
        request = self.request

        # Allow pages to be filtered to a specific type
        try:
            models = page_models_from_string(request.GET.get('type', 'wagtailcore.Page'))
        except (LookupError, ValueError):
            raise BadRequestError("type doesn't exist")

        if not models:
            models = [Page]

        if len(models) == 1:
            queryset = models[0].objects.all()
        else:
            queryset = Page.objects.all()

            # Filter pages by specified models
            queryset = filter_page_type(queryset, models)

        # Filter by site
        if request.site:
            queryset = queryset.descendant_of(request.site.root_page, inclusive=True)
        else:
            # No sites configured
            queryset = queryset.none()

        return queryset

and then while registering endpoints use:

api_router.register_endpoint('pages', DraftPagesAPIEndpoint)

You can use it now with draft query param as ?draft=true in the endpoint.

Leave a comment