wagtail Web API 経由 でデータを取得する


Wagtail API v2 Configuration Guide — Wagtail 2.0a0 documentation を参考に、API 経由で Blog データの取得ができるか試してみました。
試してみた結果を記載します。


前提

以下の環境で作業は実施しています。

  • OS

    % sw_vers
    ProductName:    Mac OS X
    ProductVersion: 10.13.1
    BuildVersion:   17B1003
    

  • Python の Version

    % python3 -V
    Python 3.6.2
    

  • wagtail の Version

    % python3 -m pip list --format=columns | grep wagtail
    wagtail                           1.13.1  
    

  • wagtail プロジェクトについて

    wagtail start mysite
    
    mysite というプロジェクトを作っている想定で、パスは記載します。

  • 取得するデータについて
    wagtail Your first Wagtail site を参考に、Blog を作る | Monotalk で Blog を作成しています。
    このデータを取得する API を記載します。


設定

INSTALLED_APPS に wagtail.api.v2 を追加する

wagtail.api.v2base.py に追加します。

  • mysite/mysite/settings/base.py
    INSTALLED_APPS = [  
        ... 
        'wagtail.api.v2',
        ...
    }
    

api.py を作成する

api.py を作成します。
Page データ取得用途、Image データ取得用途、Document データ取得用途でそれぞれ API が用意されており、それを使用します。

  • mysite/mysite/api.py1
    # api.py
    from wagtail.api.v2.endpoints import PagesAPIEndpoint
    from wagtail.api.v2.router import WagtailAPIRouter
    from wagtail.wagtailimages.api.v2.endpoints import ImagesAPIEndpoint
    from wagtail.wagtaildocs.api.v2.endpoints import DocumentsAPIEndpoint
    
    # Create the router. "wagtailapi" is the URL namespace
    api_router = WagtailAPIRouter('wagtailapi')
    
    # Add the three endpoints using the "register_endpoint" method.
    # The first parameter is the name of the endpoint (eg. pages, images). This
    # is used in the URL of the endpoint
    # The second parameter is the endpoint class that handles the requests
    api_router.register_endpoint('pages', PagesAPIEndpoint)
    api_router.register_endpoint('images', ImagesAPIEndpoint)
    api_router.register_endpoint('documents', DocumentsAPIEndpoint)
    

urls.py に、api の url を登録する

api の url を urls.py に追加します。

from .api import api_router

urlpatterns = [
    ...
    url(r'^api/v2/', api_router.urls),
    ...
]    

API 実行

  • Page API
    http://127.0.0.1:8000/api/v2/pages にアクセスすると、以下のような JSONが返却されます。

    {
        "meta": {
            "total_count": 6
        },
        "items": [
            {
                "id": 3,
                "meta": {
                    "type": "home.HomePage",
                    "detail_url": "http://localhost/api/v2/pages/3/",
                    "html_url": "http://localhost/",
                    "slug": "home",
                    "first_published_at": null
                },
                "title": "Home"
            },
            {
                "id": 4,
                "meta": {
                    "type": "blog.BlogIndexPage",
                    "detail_url": "http://localhost/api/v2/pages/4/",
                    "html_url": "http://localhost/blog/",
                    "slug": "blog",
                    "first_published_at": "2018-01-13T15:25:27.312208Z"
                },
                "title": "Blog Index Page"
            },
            {
                "id": 5,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/5/",
                    "html_url": "http://localhost/blog/my-first-post/",
                    "slug": "my-first-post",
                    "first_published_at": "2018-01-13T15:30:54.114605Z"
                },
                "title": "My first Post"
            },
            {
                "id": 6,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/6/",
                    "html_url": "http://localhost/blog/my-first-post/my-seconds-post/",
                    "slug": "my-seconds-post",
                    "first_published_at": "2018-01-13T15:29:14.568634Z"
                },
                "title": "My seconds Post"
            },
            {
                "id": 7,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/7/",
                    "html_url": "http://localhost/blog/my-se/",
                    "slug": "my-se",
                    "first_published_at": "2018-01-13T15:31:55.598228Z"
                },
                "title": "My seconds Post"
            },
            {
                "id": 8,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/8/",
                    "html_url": "http://localhost/blog/my-third-post/",
                    "slug": "my-third-post",
                    "first_published_at": "2018-01-13T15:32:48.907954Z"
                },
                "title": "My third Post"
            }
        ]
    }
    

  • Image API
    http://127.0.0.1:8000/api/v2/images にアクセスすると、以下 JSON が返却されます。登録がないので、空です。

    {
        "meta": {
            "total_count": 0
        },
        "items": []
    }
    

  • Document API
    http://127.0.0.1:8000/api/v2/documents にアクセスすると、以下 JSON が返却されます。登録がないので、空です。

    {
        "meta": {
            "total_count": 0
        },
        "items": []
    }
    


Page API を 条件を指定して実行する

Blog データだけを取得したかったので、Wagtail API v2 Usage Guide — Wagtail 2.0a0 documentation の記載を参考に、条件を指定してみます。

  • Blog 記事のみを指定して取得する http://127.0.0.1:8000/api/v2/pages?type=blog.BlogPage でアクセスすると、以下 JSON が 返却されます。
    BlogPage のみに絞り込まれます。

    {
        "meta": {
            "total_count": 4
        },
        "items": [
            {
                "id": 5,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/5/",
                    "html_url": "http://localhost/blog/my-first-post/",
                    "slug": "my-first-post",
                    "first_published_at": "2018-01-13T15:30:54.114605Z"
                },
                "title": "My first Post"
            },
            {
                "id": 6,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/6/",
                    "html_url": "http://localhost/blog/my-first-post/my-seconds-post/",
                    "slug": "my-seconds-post",
                    "first_published_at": "2018-01-13T15:29:14.568634Z"
                },
                "title": "My seconds Post"
            },
            {
                "id": 7,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/7/",
                    "html_url": "http://localhost/blog/my-se/",
                    "slug": "my-se",
                    "first_published_at": "2018-01-13T15:31:55.598228Z"
                },
                "title": "My seconds Post"
            },
            {
                "id": 8,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/8/",
                    "html_url": "http://localhost/blog/my-third-post/",
                    "slug": "my-third-post",
                    "first_published_at": "2018-01-13T15:32:48.907954Z"
                },
                "title": "My third Post"
            }
        ]
    }
    

  • Blog 記事のみをページング指定して取得する http://127.0.0.1:8000/api/v2/pages?type=blog.BlogPage&offset=3&limit=1 でアクセスすると、以下 JSON が 返却されます。
    4件目のみ、1件だけ取得できます。

    {
        "meta": {
            "total_count": 4
        },
        "items": [
            {
                "id": 8,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/8/",
                    "html_url": "http://localhost/blog/my-third-post/",
                    "slug": "my-third-post",
                    "first_published_at": "2018-01-13T15:32:48.907954Z"
                },
                "title": "My third Post"
            }
        ]
    }
    


取得項目を拡張する

BlogPage に API フィールドを追加します。

  • mysite/blog/models.py

    from wagtail.api import APIField
    
    class BlogPage(Page):
        date = models.DateField("Post date")
        intro = models.CharField(max_length=250)
        body = RichTextField(blank=True)
    
        search_fields = Page.search_fields + [
            index.SearchField('intro'),
            index.SearchField('body'),
        ]
    
        content_panels = Page.content_panels + [
            FieldPanel('date'),
            FieldPanel('intro'),
            FieldPanel('body', classname="full"),
        ]
    
        api_fields = [
            APIField('date'),
            APIField('intro'),
            APIField('body'),
        ]
    

  • Blog 記事のみをページング指定して取得する http://127.0.0.1:8000/api/v2/pages?type=blog.BlogPage&offset=3&limit=1&fields=date,intro,body にアクセスすると、以下のような JSON が返却されます。
    field に取得項目として指定しないと、dateintrobody は取得できませんでした。

    {
        "meta": {
            "total_count": 4
        },
        "items": [
            {
                "id": 8,
                "meta": {
                    "type": "blog.BlogPage",
                    "detail_url": "http://localhost/api/v2/pages/8/",
                    "html_url": "http://localhost/blog/my-third-post/",
                    "slug": "my-third-post",
                    "first_published_at": "2018-01-13T15:32:48.907954Z"
                },
                "title": "My third Post",
                "date": "2018-01-14",
                "intro": "My third Blog Post",
                "body": "<p>My third Blog Post</p>"
            }
        ]
    }
    

API で データを取得することができました。実際に使用する場合は、セキュリティ設定等が別途必要かと思います。
wagtail/endpoints.py at master · wagtail/wagtail を見る限り、Django REST Framework に依存していますので、そちらの設定を施せば、セキュリティ関連設定はできそうに思いました。
そちらは、後日実施してみようかと思います。
以上です。


  1. 開発中の version 2.0 では、wagtail.wagtailimages は、wagtail.images に、 wagtail.wagtaildocs は、wagtail.documents に移動するようです。 

コメント