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

このエントリーをはてなブックマークに追加