Serializer編 -- 忙しい人のためのDjango + DjangoRestFramework
Serializerとは
dict形式のJSONデータとPythonオブジェクトを相互変換するオブジェクト。
dict → Pythonオブジェクトの変換ではdictの値のバリデーションも行う。
Serializerを定義する
Model編で定義したDivisionモデルのSerializerを作るときは、
-
rest_framework.serializers.Serializerを継承してクラスを定義する。 - 変換先のPythonオブジェクトにある属性を
DivisionSerializerクラスにも定義する。- ここでは
Divisionにあるidとnameを定義。
- ここでは
- 定義した属性
id, nameに、変換先のPythonオブジェクトDivisionの属性の型に合わせたserializers.XXXFieldのインスタンスを渡す。- ここでは
idが数値型、nameが文字列型なのでIntegerField, CharFieldを渡す。 -
Fieldの一覧はこちら。
- ここでは
from rest_framework import serializers
from api.models import Division
class DivisionSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=30)
ここまでで、Divisionオブジェクト → JSONの変換ができるようになる。
さらに、逆の JSON → Divisionオブジェクト変換を可能にするために、Divisionオブジェクトを生成するメソッドを定義する。
-
createメソッドとupdateメソッドを作成する。-
createはdict形式のJSONデータを第一引数に。 -
updateは更新対象のPythonオブジェクト (ここではDivision) を第1引数、dict形式のJSONデータを第2引数に。
-
-
createメソッドを、JSONデータからPythonオブジェクトを生成して返すように実装する。- ここでは
Divisionを生成して返す。
- ここでは
-
updateメソッドを、更新対象オブジェクトの値をJSONデータの値に書き換えて返すように実装する。- ここでは
Divisionオブジェクトdivisionのnameを更新してdivision自体を返す。
- ここでは
from rest_framework import serializers
from api.models import Division
class DivisionSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=30)
def create(self, validated_data: dict):
""".save()を既存のDivisionを引数に**渡さず**呼ぶ時に使う"""
division = Division(**validated_data)
division.save()
return division
def update(self, division, validated_data: dict):
""".save()を既存のDivisionを引数に**渡して**呼ぶ時に使う"""
division.name = validated_data.get("name", division.name)
division.save()
return division
createとupdateには追加でなにか操作を加えても良い。ここでは生成/更新したDivisionをDBに保存している。
JSON → Pythonオブジェクト変換
dict形式のJSONデータからPythonオブジェクトを生成するには、まず定義したSerializerインスタンスをJSONデータを渡して生成し、
json_data = {"id": 3, "name": "Development"}
serializer = DivisionModelSerializer(data=json_data)
バリデーションのために.is_valid()を呼び、
serializer.is_valid() # json_dataの値や型が間違っているとFalseになる。
.save()メソッドを呼ぶ。
division: Division = serializer.save()
バリデーション前にsaveは呼べないので、必ず最初に.is_validを呼び出す。
json_dataの値やその型が間違っていると、.is_validはFalseとなり、.saveは呼べない。
Pythonオブジェクト → JSON変換
Pythonオブジェクトdivision: Divisionからdict形式のJSONデータを生成するには、Pythonオブジェクトを渡してSerializerインスタンスを生成し、.dataにアクセスする。
s = DivisionModelSerializer(division)
json_data: dict = s.data
Modelオブジェクト <-> JSON変換を簡単に書けるModelSerializer
SerializerオブジェクトはDjangoのModelクラスを変換するために定義されることが多いので、Modelクラス専用のクラスModelSerializerが用意されている。これを使うと、最初に定義したDivisionSerializerは以下のように簡単に定義できる。
class DivisionModelSerializer(serializers.ModelSerializer):
class Meta:
model = Division
fields = ["id", "name"]
Metaクラスのmodelに変換先のオブジェクト、fieldsにSerializerで変換したいモデルの属性名を指定する。
これだけで、DivisionSerializerと全く同じ動きをする。
Discussion