djangodjango-rest-frameworkwagtailwagtail-apiv2

How to filter images by collection in Wagtail API v2


I have a Page type with a foreign key to Collections:

class PageWithManyPhotos(Page):
    collection = models.ForeignKey("wagtailcore.Collection", ...)

I would like to retrieve all images of the collection selected for a page via the API. Ideally from the pages endpoint, but from the images endpoint would do too (it'd need an extra request, first to get the collection id and then to filter images by collection)

1st approach

When I add an APIField to my Page model: api_fields = [APIField("collection", serializer=CollectionSerializer())]

class CollectionSerializer(ModelSerializer):
    images = ImageSerializer(read_only=True, many=True)

    class Meta:
        model = Collection
        # fields = ["id", "name", "images"]
        exclude = []

and make a request at /api/v2/pages/?type=base.GalleryPage&fields=collection, I get a reply but without the images:

 "collection": {
                "id": 8,
                "path": "000100050003",
                "depth": 3,
                "numchild": 0,
                "name": "Collection 1"
            }

I cannot get the reverse relationship. Perhaps because Collection is an MP_Node and not a models.Model?

2nd approach

I also tried the second aproach, to add a custom viewset in the /api/v2/images/?collection=<collection_id> endpoint and filter images by collection in the images endpoint. The collection field is not in the default fields . I tried to add it doing something like:

class CollectionField(Field):
    def get_attribute(self, instance):
        return instance

    def to_representation(self, image):
        return image.collection_id


class CustomImageSerializer(BaseSerializer):
    collection = CollectionField(read_only=True)


class CustomImagesAPIViewSet(ImagesAPIViewSet):
    meta_fields = BaseAPIViewSet.meta_fields + ["collection"]
    base_serializer_class = CustomImageSerializer


api_router.register_endpoint("images", CustomImagesAPIViewSet)


Solution

  • I am not clear from your post whether or not your second approach is giving you the output you want.

    Your first approach isn't working as is because the relationship between Collections and Images is defined with related_name="+" which means you can say my_collection.images.all(). I think you can still do this if you define your images field using SerializerMethodField and then have your get_images function return all images with collection_id = <the page's collection id>