Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wagtail getting/generating image urls from JSON api or directly

I've been using Wagtail as a headless CMS to use with a frontend application, However I noticed some limitations regarding images. Normally in your jinja template you would generate the correct image size you need and all is fine, However I don't have access to these helpers in my frontend code. I have been trying several things. for example, to solve this for simple page models and their fields I could render a custom api field like so:

api_fields = [
    # Adds information about the source image (eg, title) into the API
    APIField('feed_image'),

    # Adds a URL to a rendered thumbnail of the image to the API
    APIField('feed_image_thumbnail', serializer=ImageRenditionField('fill-100x100', source='feed_image')),
    ...
]

However this will not work for streamfield since these will only return the image id. So I figured I would use the Wagtail image API, however this does not allow me to access the direct URL either.

I find some google group answers refering to this documentation: http://docs.wagtail.io/en/v1.9/advanced_topics/images/image_serve_view.html

However this page does not seem to exists in the latest version of the documentation and doesn't seem to allow me to generate images from a url on the frontend.

Is there a way to perhaps create a url that allows me to fetch an image based on its ID?

for example: somehost:8000/images/1?width=200&height=200

Or perhaps there is some other solution I am overlooking.

I love wagtail but not having easy access to image urls really limits its API usage, I hope there is a good solution for this.

Thanks

EDIT: I managed to find this in the docs: http://docs.wagtail.io/en/v1.11.1/advanced_topics/images/image_serve_view.html

However they state:

The view takes an image id, filter spec and security signature in the URL. If these parameters are valid, it serves an image file matching that criteria.

But they don't give a clear example of what a request like that would look like or how I would generate that security signature.

like image 498
Samuel Avatar asked Aug 17 '17 10:08

Samuel


People also ask

How do I install wagtail API in Django?

Even though the API is built on Django REST Framework, you do not need to install this manually as it is already a dependency of Wagtail. Firstly, you need to enable Wagtail’s API app so Django can see it. Add wagtail.api.v2 to INSTALLED_APPS in your Django project settings: # settings.py INSTALLED_APPS = [ ... 'wagtail.api.v2', ... ]

How to show data using image URLs extracted from JSON file?

In the above example, I am using a <div> element to show the data with the images using image URLs extracted from the JSON file. You can use a <table> instead of <div> to show the data. I have explained in detail about the XMLHttpRequest object here.

How do I create a JSON file with an image?

It has 3 objects, the ID, Name and Image. The value for the Image object must have a URL (or the location of the files). Open the Notepad and copy and paste the above data as it is. Save the file in .json format. I have named it data-with-image.json.

What is an endpoint in wagtail?

Each content type (such as pages, images and documents) has its own endpoint. Endpoints are combined by a router, which provides the url configuration you can hook into the rest of your project. Documents wagtail.documents.api.v2.views.DocumentsAPIViewSet You can subclass any of these endpoint classes to customise their functionality.


1 Answers

One (slightly hacky) way to get an image rendition as part of the StreamField data structure is to override ImageChooserBlock's get_api_representation method:

from wagtail.wagtailimages.blocks import ImageChooserBlock as DefaultImageChooserBlock

class ImageChooserBlock(DefaultImageChooserBlock):
    def get_api_representation(self, value, context=None):
        if value:
            return {
                'id': value.id,
                'title': value.title,
                'large': value.get_rendition('width-1000').attrs_dict,
                'thumbnail': value.get_rendition('fill-120x120').attrs_dict,
            }

Using this version of ImageChooserBlock in your StreamField definition will then give you 'large' and 'thumbnail' renditions as part of the API response, rather than just the image ID.

like image 169
gasman Avatar answered Sep 27 '22 22:09

gasman