こんにちは、増山です。最近はDjango REST Frameworkを使ってiOS, React.js用のバックエンドを書いたり、Dockerを詳しく調べたりしています。
Django, Django REST Frameworkの構造を深くまで知りたくてソースコードを読むのが趣味です。
Serializerのcontextって何?
今回のテーマは、DRFのデータのシリアル化に使われるSerializer
のcontext
について理解することです。出てくる単語の簡単な説明も交えて説明していきたいと思います。
Serializerとは?
Serializerは、アプリケーションが送受信するデータをバリデートし、さらにシリアル化してくれるものです。ただし、ここで言うシリアル化については、Serializerのみではバイト列にはならず、単一の辞書型、またはリスト型(many=Trueのとき)の文字列に変換することになります。Serializerについての詳しい記事も今後書こうと思っているのでそこでソースコードやドキュメントを見ながら具体的に説明したいと思います。
Serializerをインスタンス化する際の引数
serializer = Serializer(instance, data=data, partial=True)
や、
serializer = Serializer(queryset, many=True)
などのように、Serializerをインスタンスかする時には必要な引数があります。
dataには、例えばPOSTされたデータをrequest.dataなどから取得して格納することで、Serializerがis_valid()を呼べるようになり、データバリデートすることができます。
このまま説明し続けると脱線しすぎてもう一回線路に乗るくらいの大脱線をしそうなので、ここら辺の解説も他の記事に書こうと思います。
context引数について
本題です。
context
を引数に含めるパターンは大きく分けて2つあります。
- Hyperlink系のSerializerの機能を使っているとき
- requestなど、何かしらの情報をSerializer内部で使いたいとき
1. Hyperlink系のSerializerの機能を使っているとき
Serializerで明示的にcontext使ってないのになんでcontext渡さなきゃいけないの?って思ったときは大抵の場合これです。
drfでは、レスポンスに含めるデータとして、オブジェクト自身のurlを使うことができます。
drfの公式ドキュメントにも書いてありますが、そのときSerializerは、正しくURLを表現するためにViewが受け取るrequestオブジェクトを必要とします。
2. requestなど、何かしらの情報をSerializer内部で使いたいとき
単純なコンテキストの受け渡しにももちろん使うことができます。やり方は、Serializerをインスタンスかする時に、
serializer = Serializer(context={'名前': 渡したいデータ})
として、Serializer内部では、
self.context.get('名前', デフォルト値)
とするだけです。
終わりに
DRFは、ドキュメントがすごくしっかりしているので読めば大体わかると思います。初めて記事を投稿するので、ここが良くないとかここが良いとか教えていただけるとありがたいです。すぐに改善します。
公式ドキュメント:Django Rest Framework