Django python rest frameworkでrelationalなDBのSerialize対応をする
前回一体多に対応するModelの作成を行なったので、
今回は、そのModelのSerialize・Deserializationに対応したいと思います。
以前Serializeするためのクラスを作るために、ModelSerializerクラスを継承しましたが、
今回は、HyperlinkedModelSerializerクラスを継承します。
Serializeのためのクラスを作成する
restful01/newFlower内にserializers.pyを新たに作成します。
FlowerCategorySerializerクラス
まず、FlowerCategoryモデルをSerialize化するためのFlowerCategorySerializerクラスを作成します。
from newFlowers.models import FlowerCategory
from newFlowers.models import Flower
from newFlowers.models import Farmer
from newFlowers.models import Competition
import newFlowers.views
class FlowerCategorySerializer(serializers.HyperlinkedModelSerializer):
flowers = serializers.HyperlinkedRelatedField(
many=True,
read_only=True,
view_name='flower-detail')
class Meta:
model = FlowerCategory
fields = (
'url',
'pk',
'name',
'flowers')
まず、HyperlinkedRelatedFieldインスタンスをもつflowerを持たせます。
many=True,read_only=Trueとすることで、一体多、readonly属性にしています。
view_nameはbrowsable api上で表示される名前です。
続いて、Meta classを見ていきます。
modelには、対象のモデル名を
filedsには、カラムを入れます。
urlは、HyperlinkedModelSerializerで必要なカラムで、pk(primary key)とtupleで使います。
flowersはFlowerCategoryを外部キーにもつFlowerModelにrelated_nameとして定義していました。
こうすることで、一体多の関係が築けます。
nameはFlowerCategoryのカラムとして定義していました。
FlowerSerializerクラス
続いて、FlowerModelをSerialize化するための、FlowerSerializerクラスを定義します。
class FlowerSerializer(serializers.HyperlinkedModelSerializer):
flower_category = serializers.SlugRelatedField(queryset=FlowerCategory.objects.all(), slug_field='name')
class Meta:
model = Flower
fields = (
'url',
'name',
'flower_category',
'production_date',
'has_it_competed',
'inserted_timestamp')
このクラスでは、flower category名をbrowsable api上で表示するために、SlugRelatedFieldを使っています。
fieldには、Flower Modelに定義したカラムと、urlを入れています。
またFlowerCategoryとは異なりprimary keyは不要なので定義していません。
CompetitionSerializerクラス
続いて、CompetitionモデルをSerializeするための
CompetitionSerializerクラスを定義します。
class CompetitionSerializer(serializers.HyperlinkedModelSerializer):
# Display all the details for the related flower
flower = FlowerSerializer()
class Meta:
model = Competition
fields = (
'url',
'pk',
'score',
'score_achievement_date',
'flower')
Competitionモデルには、flowerとfarmerを外部キーに持たせましたが、
farmerに関しては、farmerSerializerクラスで、CompetitionSerializerクラスを持たせるので、ここでは含めません。
FarmerSerializerクラス
続いて、FarmerモデルをSerializeするための
FarmerSerializerクラスを定義します。
class FarmerSerializer(serializers.HyperlinkedModelSerializer):
competitions = CompetitionSerializer(many=True, read_only=True)
gender = serializers.ChoiceField(
choices=Farmer.GENDER_CHOICES)
gender_description = serializers.CharField(
source='get_gender_display',
read_only=True)
class Meta:
model = Farmer
fields = (
'url',
'name',
'gender',
'gender_description',
'competitions_count',
'inserted_timestamp',
'competitions')
まず、先ほど説明したようにCompetitionSerializerをインスタンスとして保持するため、competitionsを持っています。
また、Competitionモデルを定義した時に、related_nameにcompetitionsと定義したため、名前をcompetitionsにしています。
FarmerCompetitionSerializerクラス
CompetitionSerializerクラスでは、 Farmerクラスは重複するために持たせなかったので、
Competitionに関連したFarmerとFlower両方の出力に対応したのが、FarmerCompetitionSerializerクラスです。
class FarmerCompetitionSerializer(serializers.ModelSerializer):
# Display the farmer's name
farmer = serializers.SlugRelatedField(queryset=Farmer.objects.all(), slug_field='name')
# Display the flower's name
flower = serializers.SlugRelatedField(queryset=Floer.objects.all(), slug_field='name')
class Meta:
model = Competition
fields = (
'url',
'pk',
'score',
'score_achievement_date',
'farmer',
'flower')
こちらを参考に、知識をまとめています。
初版:2018/6/24