Learn Wagtail CMS Course

Headless CMS: Custom Wagtail Image Serializer

In the previous lesson we ran into an issue where a ForeignKey image was not serializable. In this video we're going to address that problem by creating a custom serializer using Django Rest Framework and Wagtails v2 API.

In true Wagtail fashion, we don't need to do very much work. I know I've said this about 10,000 times by now, but this is one of the biggest values behind Wagtail CMS: You can achieve almost anything in such a short amount of time, and still have efficient, maintainable and elegant code.

Let's dive in!

The Serializer

A serializer really just takes some information from Django (or in our case Wagtail) and turns it into a JSON response for the browser and frontend frameworks like React to consume.

from rest_framework.fields import Field

class ImageSerializedField(Field):
    """A custom serializer used in Wagtails v2 API."""

    def to_representation(self, value):
        """Return the image URL, title and dimensions."""
        return {
            "url": value.file.url,
            "title": value.title,
            "width": value.width,
            "height": value.height,
        }

This takes the image as a value. You'll see where it's getting the image (as the value) in the code below. But if you wanted to extend this to any other field type, you can absolutely do that too.

from django.db import models

from modelcluster.fields import ParentalKey
from wagtail.api import APIField
from wagtail.core.models import Orderable
from wagtail.images.edit_handlers import ImageChooserPanel


class BlogAuthorsOrderable(Orderable):
    """This allows us to select one or more blog authors from Snippets."""

    page = ParentalKey("blog.BlogDetailPage", related_name="blog_authors")
    author = models.ForeignKey(
        "blog.BlogAuthor",
        on_delete=models.CASCADE,
    )

    @property
    def author_image(self):
        return self.author.image

    api_fields = [
        # This is using a custom django rest framework serializer
        APIField("author_image", serializer=ImageSerializedField()),
    ]

class BlogAuthor(models.Model):
    """Blog author for snippets."""

    image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.SET_NULL,
        null=True,
        blank=False,
        related_name="+",
    )

    panels = [
        ImageChooserPanel("image"),
    ]

The Git Commit

Interested in seeing the full git commit? Well don't be too shocked when you don't see very many changes ;) Wagtail makes the lives of developers super simple.

https://github.com/CodingForEverybody/learn-wagtail/commit/2c52d07b9723296b6c11b4b2c16c26b6263b9928