mnowotka
mnowotka

Reputation: 17218

Wagtail API - how to expose snippets

Imagine I have a Snippet and a Page containing it:

@register_snippet
class MySnippet(models.Model):
    content = models.CharField(max_length=255)


class MyPage(Page):
    snippet = models.ForeignKey('MySnippet', null=True, blank=True, on_delete=models.SET_NULL, related_name='+')

    api_fields = [
        APIFiled('snippet')
    ]

Now in the wagtail API page endpoint this page will look like this:

{
    "id": 1,
    "meta": { ... },
    "snippet": {
        "id": 1,
        "meta": {
            "type": "my_module.MySnippet"
        }
    }
}

What can I do to make this endpoint displaying snippet's content?

Also, how do I create a separate API endpoint only for snippets?

Upvotes: 4

Views: 2288

Answers (3)

theberzi
theberzi

Reputation: 2645

An up to date APIViewSet (which older Wagtail versions would refer to as an APIEndpoint) would be:

class MyAPIViewSet(BaseAPIViewSet):
    # BaseSerializer is enough for simple fields.
    base_serializer_class = BaseSerializer
    body_fields = BaseAPIViewSet.body_fields + ["field1", "field2"]
    meta_fields = BaseAPIViewSet.meta_fields + ["field1"]
    listing_default_fields = BaseAPIViewSet.listing_default_fields + ["field1", "field2"]
    nested_default_fields = BaseAPIViewSet.nested_default_fields + ["field1"]
    name = "mymodels"
    model = MyModel

Then in api.py:

api_router.register_endpoint("mymodels", MySnippetModelAPIEndpoint)

You have to create one such ViewSet for each Snippet you want to expose through the API.

Upvotes: 0

Udit Agarwal
Udit Agarwal

Reputation: 332

Here's how I did it, it was a simple enough representation though in my case

from rest_framework import serializers

class MyPage(Page):
    snippet = models.ForeignKey('MySnippet', null=True, blank=True, on_delete=models.SET_NULL, related_name='+')

    api_fields = [
        APIField('snippet', serializer=serializers.StringRelatedField(many=True))
    ]

And you can add a 'str' method to your snippet

@register_snippet
class MySnippet(models.Model):
    content = models.CharField(max_length=255)

        def __str__(self):
            return self.content

Upvotes: 5

LazerFriends
LazerFriends

Reputation: 421

I'm not sure how to answer the main question, but I can help with creating separate API endpoints for snippets.

You have to create an endpoints.py file in your app root, using the existing Wagtail endpoint classes as a base, such as BaseAPIEndpoint

Then, register the new endpoint in your api.py file.

endpoints.py

from wagtail.api.v2.endpoints import BaseAPIEndpoint
from .models import MySnippetModel

class MySnippetModelAPIEndpoint(BaseAPIEndpoint):

    model = MySnippetModel

    body_fields = BaseAPIEndpoint.body_fields + [
        'field_1',
        'field_2',
        'field_3',
    ]

    listing_default_fields = BaseAPIEndpoint.listing_default_fields = [
        'field_1',
        'field_2',
        'field_3',
    ]

api.py

from .endpoints import MySnippetModelAPIEndpoint

...

sua_api_router.register_endpoint('snippets', MySnippetModelAPIEndpoint)

I would also look at the endpoints.py file in Wagtail core, so you can see what else you can extend or modify.

https://github.com/wagtail/wagtail/blob/master/wagtail/api/v2/endpoints.py

Upvotes: 6

Related Questions