MENU

Django Ninjaチュートリアル14(カスタムレンダラー)

Django Ninjaチュートリアル14(カスタムレンダラー)

前回までの記事はこちらです。

前回までの記事が読まれている前提で書いていきますので、まだ読んでいない方はこちらから読み進めて追いついてください。

それでは始めていきましょう。

目次

カスタムレンダラー

今回は、こちらの公式ドキュメントからカスタムレンダラーについてみていきます。

Django Ninjaのカスタムレンダラー

通常、REST APIで最も一般的なレスポンスタイプはJSONです。
Django Ninjaでは、独自のカスタムレンダラーの定義をサポートしているため、独自のメディアタイプを柔軟に設計することができます。

それでは早速、例を見ながら進めていきます。

レンダラーの作成

独自のレンダラーを作成するには、ninja.renderers.BaseRendererを継承し、レンダーメソッドをオーバーライドする必要があります。
そして、作成したインスタンスをNinjaAPIクラスにrenderer引数として渡す必要があります。

実際のコードは以下のようになります。

from lib2to3.pytree import Base
from ninja import NinjaAPI
from ninja.renderers import BaseRenderer

class MyRenderer(BaseRenderer):
  media_type = "text/plain"
  
  def render(self, request, data, *, response_status):
    return ...

app_v6 = NinjaAPI(
  title = "Django-Ninja Sample App5",
  version = "1.0.5",
  renderer = MyRenderer()
)

renderメソッドは以下の引数を必要とします。

  • request:Httpリクエストのオブジェクト
  • data:シリアライズに必要なオブジェクト
  • response_status:クライアントサイドから返されるHTTPステータスコード(int型である必要があります)

また、レスポンスのcontent-type headerを設定するためにmedia_typeの属性をクラスに設定する必要があります。

以上が、独自レンダラー設定の基本になります。

ORJSONによるレンダラー

orjsonは、Python用の高速で正確なJSONライブラリです。
JSON用の最速のPythonライブラリとしてベンチマークされ、標準ライブラリや他のサードパーティ製のJSONライブラリよりも正確とされています。
また、dataclassdatetimenumpyUUIDインスタンスをネイティブにシリアル化します。

orjsonを使用するレンダラークラスの例は以下のとおりです。

from ninja import NinjaAPI
from ninja.renderers import BaseRenderer

class MyRenderer(BaseRenderer):
  media_type = "text/plain"
  
  def render(self, request, data, *, response_status):
    return ...

# add
class ORJSONRenderer(BaseRenderer):
  media_type = "application/json"
  
  def render(self, request, data, *, response_status):
    return orjson.dumps(data)

app_v6 = NinjaAPI(
  title = "Django-Ninja Sample App5",
  version = "1.0.5",
  # renderer = MyRenderer(), # comment out
  renderer = ORJSONRenderer() # add
)

設定方法は、独自レンダラーの作成と同じ方法です。
dumps()メソッドは、Pythonで生成されたリスト型や辞書型のデータをJSON形式に変換するメソッドです。
その引数には、シリアライズに必要なデータをdata引数で受け取っています。

XMKレンダラー

次に見ていくのは、XML形式に対応するレンダラーです。
これは例を示しておきます(以下の例では、Django-REST-framework-xmlのコードを利用しています)。

from io import StringIO
from django.utils.encoding import force_str
from django.utils.xmlutils import SimplerXMLGenerator
from ninja import NinjaAPI
from ninja.renderers import BaseRenderer


class XMLRenderer(BaseRenderer):
    media_type = "text/xml"

    def render(self, request, data, *, response_status):
        stream = StringIO()
        xml = SimplerXMLGenerator(stream, "utf-8")
        xml.startDocument()
        xml.startElement("data", {})
        self._to_xml(xml, data)
        xml.endElement("data")
        xml.endDocument()
        return stream.getvalue()

    def _to_xml(self, xml, data):
        if isinstance(data, (list, tuple)):
            for item in data:
                xml.startElement("item", {})
                self._to_xml(xml, item)
                xml.endElement("item")

        elif isinstance(data, dict):
            for key, value in data.items():
                xml.startElement(key, {})
                self._to_xml(xml, value)
                xml.endElement(key)

        elif data is None:
            # Don't output any value
            pass

        else:
            xml.characters(force_str(data))


api = NinjaAPI(renderer=XMLRenderer())

【著作権】こちらのコードはDjango-REST-framework-xmlからコードを共有しています。

https://github.com/jpadilla/django-rest-framework-xml/blob/master/rest_framework_xml/renderers.py

最後に

今回はレンダラーの設定方法についてまとめました。
最後のXMLレンダラーは公式ドキュメントのままです。
ご了承ください。

今回の記事で取り上げたレンダラーの設定方法を理解しておくことで、フロントエンドや他のサイト等から受け取ったデータの形式に応じて、適切にデータ処理を行うことができると思います。
Django Ninjaを使用する際の参考になれば嬉しいです。

次回は、routerを利用したAPIのルーティング設定についてみていきます。

よろしければ次回もご覧ください。
では、今回は以上です。

Django Ninjaチュートリアル14(カスタムレンダラー)

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

はじめまして、ふじです。
Python、Django、FastAPI、React.js、Next.jsを学習している、ずっと文系のプログラミング独学者です。

目次