Ephes Blog

Miscellaneous things. Mostly Weeknotes and links I stumbled upon.

Date -

How to Pass a Request Object from Wagtail API to a Page

, Jochen

Introduction

When using Wagtail's API to fetch website pages, the APIField class allows you to add custom fields. But what if you also need to incorporate the request object into your custom field?

Why the Request Object is Important

I ran into this issue because I wanted to fetch the fully-rendered HTML of a page via the Wagtail API, eliminating the need to manually render the StreamField in my Vue.js blog theme.

Code Example

To achieve this, use the APIField class as demonstrated in the code snippet below:

from wagtail.models import Page
from wagtail.api import APIField

from rest_framework.fields import Field

class HtmlField(Field):
    def to_representation(self, page):
        return page.serve(self.context["request"])

class Post(Page):
    ...
    api_fields = [
        APIField("html", serializer=HtmlField(source="*")),
    ]

Understanding the source="*" Parameter

The `source="*"` parameter is special: it enables the `to_representation` method to work with the entire page object, rather than just a specific field on that page.


Using staticfiles with STORAGES in Django 4.2

, Jochen

The other day I was trying to improve a management command of django-cast to make it easier to backup media files like images and videos. There's already an existing command, but it had to assume that you stored your media files on s3 and wanted the backup to be stored on the local filesystem. It would be great if you could configure your production and backup storage and have the backup command work either way. And the new STORAGES setting added in Django 4.2 looks like a perfect fit for this. So I tried using such a configuration:

STORAGES = {
    "default": {"BACKEND": "config.settings.local.CustomS3Boto3Storage"},
    "staticfiles": {
        "BACKEND": "django.core.files.storage.FileSystemStorage",
        "OPTIONS": {
            "location": "staticfiles",
            "base_url": "/static/",
        },
    },
    "production": {"BACKEND": "config.settings.local.CustomS3Boto3Storage"},
    "backup": {
        "BACKEND": "django.core.files.storage.FileSystemStorage",
        "OPTIONS": {
            "location": ROOT_DIR.path("backups").path("media"),
        },
    },
}

But it didn't work. It took me longer than I would like to admit to figure out that I should have used this config:

STORAGES = {
    "default": {"BACKEND": "config.settings.local.CustomS3Boto3Storage"},
    "staticfiles": {"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"},
    "production": {"BACKEND": "config.settings.local.CustomS3Boto3Storage"},
    "backup": {
        "BACKEND": "django.core.files.storage.FileSystemStorage",
        "OPTIONS": {
            "location": ROOT_DIR.path("backups").path("media"),
        },
    },
}

If you want to replace django.contrib.staticfiles.storage.StaticFilesStorage with whitenoise for production, it's sufficient overwrite the backend in the production settings like this:

STORAGES["staticfiles"]["BACKEND"] = "whitenoise.storage.CompressedManifestStaticFilesStorage"