Search by

    Django REST Frameworkのチュートリアル(Tutorial 5 Relationships & Hyperlinked APIs)をやってみた

    Django REST Frameworkの公式チュートリアル(5 Relationships & Hyperlinked APIs)をやってみた時の不明点、気付きをまとめておく。

    概要

    現時点のAPIでは、ユーザーとスニペットの情報はプライマリキーでリレーションされている。 この章では、リレーションにハイパーリンクを利用することでその凝集性と発見性を改善します。とのこと。確かにプライマリキーを見せられてもよくわからないよねとは思っていた。

    ルートエンドポイントを作成する

    現時点では、スニペットとユーザーそれぞれに対してエンドポイントが作成されているが、統一されたエンドポイントは持っていない。 これを@api_viewで実装する。

    views.py
    from rest_framework.decorators import api_view
    from rest_framework.response import Response
    from rest_framework.reverse import reserve
    
    @api_view(['GET'])
    def api_root(request, format=None):
        return Response({
            'users': reverse('user-list', request=request, format=format),
            'snippets': reverse('snippet-list', request=request, format=format)
        })

    ルートポイントがなかったので、http://127.0.0.1:8000/にアクセスしても何も結果を得られなかったが、 リバースで、ユーザーとにスニペット、それぞれのURLを表示してくれるようになった。 apiroot

    注意点が2つ

    • reverse関数

    fully-qualified URLsを返すために使用する

    • URLパターン

    URLパターンは、あとでsnippets/urls.pyにて宣言される便利な名前によって識別される。 つまり、djangoの下記の様なコードに相当する。

    some_django_template.html
    <a href="{% url 'another_URLname' %}">Home</a>
    urls.py
    path('somewhere/', TemplateView.as_view(template_name="another_django_template.html"), name='another_URLname'),

    …テンプレートを用意しなくても、勝手にhtmlを吐いてくれるのは、@api_view()デコレータのおかげってことか。

    ハイライトされスニペットのエンドポイントを作る

    ハイライトされたスニペットのエンドポイントを作成していく。 他のエンドポイントとは違って、jsonではなくHTMLでフォーマットしてデータが返ってくるようにしたい。 REST frameworkでは2つの方法を提供している。1つはテンプレートを使うこと。もう1つは最初にHTMLをレンダーする方法。今回は後者の方法を利用する。

    もう1つ注意する必要があるのは、既存の具体的なジェネリックViewがないこと。Viewはオブジェクトのインスタンスを返すのではなく、そのプロパティーを返す。

    ジェネリックViewがないので自分で作る。

    snippets/views.py
    from rest_framework import renderers
    from rest_framework.response import Response
    
    class SnippetHighlight(generics.GenericAPIView):
        queryset = Snippet.objects.all()
        renderer_classes = [renderers.StaticHTMLRenderer]
    
        def get(self, request, *args, **kwargs):
            snippet = self.get_object()
            return Response(snippet.highlighted)

    ハイパーリンクされたAPIをつくる

    エンティティー間のリレーションを扱うのはwebAPIデザインにおいて、チャレンジングな側面の1つだ。 リレーションを表現する方法はたくさんある。

    • プライマリキーを使うこと
    • エンティティー間にハイパーリンクを使うこと
    • 関連するエンティティにユニークな識別スラグを使うこと
    • 関連するエンティテのデフォルトの文字列表現を使うこと(よくわからん)
    • 親の表現の中に関連するエンティティーをネストすること
    • 別のカスタム表現

    RESTはどの方法にも対応している。

    今回はハイパーリンクされたスタイルを使用する。 下記の点でモデルシリアライザーとは違う。

    • idフィールドをデフォルトで含んでいない
    • HyperlinkedIdentyFieldを使ってたurlフィールドを含んでいる。
    • リレーションはPrimaryKeyRelatedFieldの代わりにHyperlinkedRelatedFieldを使う。

    シリアライザを編集していく。

    serializers.HyperlinkedIdentityFieldをコンストラクトする時に、フォーマットにhtmlを指定することで、どんな場合でもhtmlで返す様に指定できる

    URLパターンを確定させる

    ここは見たままか。 これまで作ってきたViewやシリアライザに合わせてurlを書いていく

    ページネーションを加える

    今はいいけどスニペットの量が増えると、全てのデータを一回で返すとパフォーマンスに影響が出るかもしれない。 そうならない様に、一回のデータ送信量を調整する必要がある。

    全てのRESTフレームワークの設定はREST_FRAMEWORK辞書の中で行う。 こうすることで、他の設定と明確に分けることができる。

    APIをブラウジングする

    ブラウザでAPIを探索するとちゃんとリンク貼られていることが確認できる。シンタックスハイライトもちゃんと動いていればOKです。

    前の記事
    次の記事

    参考